Merge "Clicking on partially coverd views by other views or windows." into lmp-dev
diff --git a/Android.mk b/Android.mk
index 419b1ed..35d13d7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -204,6 +204,7 @@
 	core/java/android/os/IUserManager.aidl \
 	core/java/android/os/IVibratorService.aidl \
 	core/java/android/service/notification/INotificationListener.aidl \
+	core/java/android/service/notification/IStatusBarNotificationHolder.aidl \
 	core/java/android/service/notification/IConditionListener.aidl \
 	core/java/android/service/notification/IConditionProvider.aidl \
 	core/java/android/print/ILayoutResultCallback.aidl \
@@ -489,8 +490,11 @@
 	frameworks/base/location/java/android/location/FusedBatchOptions.aidl \
 	frameworks/base/location/java/com/android/internal/location/ProviderProperties.aidl \
 	frameworks/base/location/java/com/android/internal/location/ProviderRequest.aidl \
+	frameworks/base/media/java/android/media/AudioAttributes.aidl \
+	frameworks/base/media/java/android/media/MediaDescription.aidl \
 	frameworks/base/media/java/android/media/MediaMetadata.aidl \
 	frameworks/base/media/java/android/media/Rating.aidl \
+	frameworks/base/media/java/android/media/browse/MediaBrowser.aidl \
 	frameworks/base/media/java/android/media/session/MediaSession.aidl \
 	frameworks/base/media/java/android/media/session/PlaybackState.aidl \
 	frameworks/base/telephony/java/android/telephony/ServiceState.aidl \
diff --git a/api/current.txt b/api/current.txt
index dab4f64..a309fe6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1062,6 +1062,7 @@
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
     field public static final int restrictedAccountType = 16843733; // 0x10103d5
     field public static final int restrictionType = 16843923; // 0x1010493
+    field public static final int resumeWhilePausing = 16843955; // 0x10104b3
     field public static final int reversible = 16843851; // 0x101044b
     field public static final int right = 16843183; // 0x10101af
     field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
@@ -5525,8 +5526,8 @@
     field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT";
     field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE";
     field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.PROVISIONING_WIFI_SSID";
-    field public static int FLAG_MANAGED_CAN_ACCESS_PARENT;
-    field public static int FLAG_PARENT_CAN_ACCESS_MANAGED;
+    field public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 2; // 0x2
+    field public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 1; // 0x1
     field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
     field public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0; // 0x0
     field public static final int KEYGUARD_DISABLE_FINGERPRINT = 32; // 0x20
@@ -7838,6 +7839,7 @@
     field public static final java.lang.String EXTRA_ALLOW_MULTIPLE = "android.intent.extra.ALLOW_MULTIPLE";
     field public static final deprecated java.lang.String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE";
     field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT";
+    field public static final java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
     field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
     field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
     field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
@@ -8167,8 +8169,8 @@
   }
 
   public class RestrictionsManager {
+    method public android.content.Intent createLocalApprovalIntent();
     method public android.os.Bundle getApplicationRestrictions();
-    method public android.content.Intent getLocalApprovalIntent();
     method public java.util.List<android.content.RestrictionEntry> getManifestRestrictions(java.lang.String);
     method public boolean hasRestrictionsProvider();
     method public void notifyPermissionResponse(java.lang.String, android.os.PersistableBundle);
@@ -8410,6 +8412,7 @@
     field public static final int FLAG_MULTIPROCESS = 1; // 0x1
     field public static final int FLAG_NO_HISTORY = 128; // 0x80
     field public static final int FLAG_RELINQUISH_TASK_IDENTITY = 4096; // 0x1000
+    field public static final int FLAG_RESUME_WHILE_PAUSING = 16384; // 0x4000
     field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
     field public static final int FLAG_STATE_NOT_NEEDED = 16; // 0x10
     field public static final int LAUNCH_MULTIPLE = 0; // 0x0
@@ -8685,7 +8688,7 @@
     method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllSessions();
     method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getMySessions();
     method public android.content.pm.PackageInstaller.SessionInfo getSessionInfo(int);
-    method public android.content.pm.PackageInstaller.Session openSession(int);
+    method public android.content.pm.PackageInstaller.Session openSession(int) throws java.io.IOException;
     method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
     method public void uninstall(java.lang.String, android.content.IntentSender);
@@ -8718,16 +8721,15 @@
     method public java.lang.String[] getNames() throws java.io.IOException;
     method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
     method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
-    method public void setProgress(float);
+    method public void setStagingProgress(float);
   }
 
   public static abstract class PackageInstaller.SessionCallback {
     ctor public PackageInstaller.SessionCallback();
+    method public abstract void onActiveChanged(int, boolean);
     method public abstract void onBadgingChanged(int);
-    method public abstract void onClosed(int);
     method public abstract void onCreated(int);
     method public abstract void onFinished(int, boolean);
-    method public abstract void onOpened(int);
     method public abstract void onProgressChanged(int, float);
   }
 
@@ -8740,7 +8742,7 @@
     method public java.lang.String getInstallerPackageName();
     method public float getProgress();
     method public int getSessionId();
-    method public boolean isOpen();
+    method public boolean isActive();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
   }
@@ -8880,6 +8882,7 @@
     field public static final java.lang.String EXTRA_VERIFICATION_RESULT = "android.content.pm.extra.VERIFICATION_RESULT";
     field public static final java.lang.String FEATURE_APP_WIDGETS = "android.software.app_widgets";
     field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
+    field public static final java.lang.String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
     field public static final java.lang.String FEATURE_BACKUP = "android.software.backup";
     field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
     field public static final java.lang.String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le";
@@ -12672,17 +12675,17 @@
   public abstract class CameraCaptureSession implements java.lang.AutoCloseable {
     ctor public CameraCaptureSession();
     method public abstract void abortCaptures() throws android.hardware.camera2.CameraAccessException;
-    method public abstract int capture(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
-    method public abstract int captureBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public abstract int capture(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public abstract int captureBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract void close();
     method public abstract android.hardware.camera2.CameraDevice getDevice();
-    method public abstract int setRepeatingBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
-    method public abstract int setRepeatingRequest(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public abstract int setRepeatingBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public abstract int setRepeatingRequest(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract void stopRepeating() throws android.hardware.camera2.CameraAccessException;
   }
 
-  public static abstract class CameraCaptureSession.CaptureListener {
-    ctor public CameraCaptureSession.CaptureListener();
+  public static abstract class CameraCaptureSession.CaptureCallback {
+    ctor public CameraCaptureSession.CaptureCallback();
     method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
     method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
     method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
@@ -12691,8 +12694,8 @@
     method public void onCaptureStarted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, long);
   }
 
-  public static abstract class CameraCaptureSession.StateListener {
-    ctor public CameraCaptureSession.StateListener();
+  public static abstract class CameraCaptureSession.StateCallback {
+    ctor public CameraCaptureSession.StateCallback();
     method public void onActive(android.hardware.camera2.CameraCaptureSession);
     method public void onClosed(android.hardware.camera2.CameraCaptureSession);
     method public abstract void onConfigureFailed(android.hardware.camera2.CameraCaptureSession);
@@ -12779,7 +12782,7 @@
   public abstract class CameraDevice implements java.lang.AutoCloseable {
     method public abstract void close();
     method public abstract android.hardware.camera2.CaptureRequest.Builder createCaptureRequest(int) throws android.hardware.camera2.CameraAccessException;
-    method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract java.lang.String getId();
     field public static final int TEMPLATE_MANUAL = 6; // 0x6
     field public static final int TEMPLATE_PREVIEW = 1; // 0x1
@@ -12789,8 +12792,8 @@
     field public static final int TEMPLATE_ZERO_SHUTTER_LAG = 5; // 0x5
   }
 
-  public static abstract class CameraDevice.StateListener {
-    ctor public CameraDevice.StateListener();
+  public static abstract class CameraDevice.StateCallback {
+    ctor public CameraDevice.StateCallback();
     method public void onClosed(android.hardware.camera2.CameraDevice);
     method public abstract void onDisconnected(android.hardware.camera2.CameraDevice);
     method public abstract void onError(android.hardware.camera2.CameraDevice, int);
@@ -12803,15 +12806,15 @@
   }
 
   public final class CameraManager {
-    method public void addAvailabilityListener(android.hardware.camera2.CameraManager.AvailabilityListener, android.os.Handler);
     method public android.hardware.camera2.CameraCharacteristics getCameraCharacteristics(java.lang.String) throws android.hardware.camera2.CameraAccessException;
     method public java.lang.String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException;
-    method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
-    method public void removeAvailabilityListener(android.hardware.camera2.CameraManager.AvailabilityListener);
+    method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public void registerAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback, android.os.Handler);
+    method public void unregisterAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback);
   }
 
-  public static abstract class CameraManager.AvailabilityListener {
-    ctor public CameraManager.AvailabilityListener();
+  public static abstract class CameraManager.AvailabilityCallback {
+    ctor public CameraManager.AvailabilityCallback();
     method public void onCameraAvailable(java.lang.String);
     method public void onCameraUnavailable(java.lang.String);
   }
@@ -14050,6 +14053,7 @@
     field public static final int CONTENT_TYPE_SONIFICATION = 4; // 0x4
     field public static final int CONTENT_TYPE_SPEECH = 1; // 0x1
     field public static final int CONTENT_TYPE_UNKNOWN = 0; // 0x0
+    field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1
     field public static final int USAGE_ALARM = 4; // 0x4
     field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
@@ -14235,9 +14239,9 @@
     field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
     field public static final int ERROR = -1; // 0xffffffff
     field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
-    field public static final java.lang.String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.audio_plug_state";
-    field public static final java.lang.String EXTRA_ENCODINGS = "android.media.extra.encodings";
-    field public static final java.lang.String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.max_channel_count";
+    field public static final java.lang.String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.AUDIO_PLUG_STATE";
+    field public static final java.lang.String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS";
+    field public static final java.lang.String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.MAX_CHANNEL_COUNT";
     field public static final java.lang.String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE";
     field public static final java.lang.String EXTRA_SCO_AUDIO_PREVIOUS_STATE = "android.media.extra.SCO_AUDIO_PREVIOUS_STATE";
     field public static final java.lang.String EXTRA_SCO_AUDIO_STATE = "android.media.extra.SCO_AUDIO_STATE";
@@ -14709,7 +14713,7 @@
 
   public static final class MediaCodecInfo.CodecCapabilities {
     ctor public MediaCodecInfo.CodecCapabilities();
-    method public static android.media.MediaCodecInfo.CodecCapabilities CreateFromProfileLevel(java.lang.String, int, int);
+    method public static android.media.MediaCodecInfo.CodecCapabilities createFromProfileLevel(java.lang.String, int, int);
     method public android.media.MediaCodecInfo.AudioCapabilities getAudioCapabilities();
     method public android.media.MediaFormat getDefaultFormat();
     method public android.media.MediaCodecInfo.EncoderCapabilities getEncoderCapabilities();
@@ -16280,7 +16284,7 @@
   }
 
   public static class MediaBrowser.MediaItem implements android.os.Parcelable {
-    ctor public MediaBrowser.MediaItem(int, android.media.MediaDescription);
+    ctor public MediaBrowser.MediaItem(android.media.MediaDescription, int);
     method public int describeContents();
     method public android.media.MediaDescription getDescription();
     method public int getFlags();
@@ -16381,8 +16385,6 @@
 
   public final class MediaController {
     ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
-    method public void addCallback(android.media.session.MediaController.Callback);
-    method public void addCallback(android.media.session.MediaController.Callback, android.os.Handler);
     method public void adjustVolume(int, int);
     method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
     method public android.os.Bundle getExtras();
@@ -16397,9 +16399,11 @@
     method public android.app.PendingIntent getSessionActivity();
     method public android.media.session.MediaSession.Token getSessionToken();
     method public android.media.session.MediaController.TransportControls getTransportControls();
-    method public void removeCallback(android.media.session.MediaController.Callback);
+    method public void registerCallback(android.media.session.MediaController.Callback);
+    method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler);
     method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void setVolumeTo(int, int);
+    method public void unregisterCallback(android.media.session.MediaController.Callback);
   }
 
   public static abstract class MediaController.Callback {
@@ -16725,10 +16729,10 @@
   }
 
   public final class TvInputInfo implements android.os.Parcelable {
+    method public android.content.Intent createSettingsIntent();
+    method public android.content.Intent createSetupIntent();
     method public int describeContents();
     method public java.lang.String getId();
-    method public android.content.Intent getIntentForSettingsActivity();
-    method public android.content.Intent getIntentForSetupActivity();
     method public java.lang.String getParentId();
     method public android.content.pm.ServiceInfo getServiceInfo();
     method public int getType();
@@ -16736,7 +16740,8 @@
     method public android.graphics.drawable.Drawable loadIcon(android.content.Context);
     method public java.lang.CharSequence loadLabel(android.content.Context);
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final java.lang.String EXTRA_INPUT_ID = "inputId";
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final java.lang.String EXTRA_INPUT_ID = "android.media.tv.extra.INPUT_ID";
     field public static final int TYPE_COMPONENT = 1004; // 0x3ec
     field public static final int TYPE_COMPOSITE = 1001; // 0x3e9
     field public static final int TYPE_DISPLAY_PORT = 1008; // 0x3f0
@@ -16755,23 +16760,23 @@
     method public java.util.List<android.media.tv.TvInputInfo> getTvInputList();
     method public boolean isParentalControlsEnabled();
     method public boolean isRatingBlocked(android.media.tv.TvContentRating);
-    method public void registerListener(android.media.tv.TvInputManager.TvInputListener, android.os.Handler);
-    method public void unregisterListener(android.media.tv.TvInputManager.TvInputListener);
-    field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED";
-    field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED";
-    field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.TvInputManager.ACTION_QUERY_CONTENT_RATING_SYSTEMS";
+    method public void registerCallback(android.media.tv.TvInputManager.TvInputCallback, android.os.Handler);
+    method public void unregisterCallback(android.media.tv.TvInputManager.TvInputCallback);
+    field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
+    field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
+    field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
     field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
-    field public static final java.lang.String META_DATA_CONTENT_RATING_SYSTEMS = "android.media.tv.TvInputManager.META_DATA_CONTENT_RATING_SYSTEMS";
+    field public static final java.lang.String META_DATA_CONTENT_RATING_SYSTEMS = "android.media.tv.metadata.CONTENT_RATING_SYSTEMS";
     field public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3; // 0x3
     field public static final int VIDEO_UNAVAILABLE_REASON_TUNING = 1; // 0x1
     field public static final int VIDEO_UNAVAILABLE_REASON_UNKNOWN = 0; // 0x0
     field public static final int VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL = 2; // 0x2
   }
 
-  public static abstract class TvInputManager.TvInputListener {
-    ctor public TvInputManager.TvInputListener();
+  public static abstract class TvInputManager.TvInputCallback {
+    ctor public TvInputManager.TvInputCallback();
     method public void onInputAdded(java.lang.String);
     method public void onInputRemoved(java.lang.String);
     method public void onInputStateChanged(java.lang.String, int);
@@ -16862,10 +16867,10 @@
     method public boolean onUnhandledInputEvent(android.view.InputEvent);
     method public void reset();
     method public void selectTrack(int, java.lang.String);
+    method public void setCallback(android.media.tv.TvView.TvInputCallback);
     method public void setCaptionEnabled(boolean);
     method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
     method public void setStreamVolume(float);
-    method public void setTvInputListener(android.media.tv.TvView.TvInputListener);
     method public void tune(java.lang.String, android.net.Uri);
   }
 
@@ -16873,8 +16878,8 @@
     method public abstract boolean onUnhandledInputEvent(android.view.InputEvent);
   }
 
-  public static abstract class TvView.TvInputListener {
-    ctor public TvView.TvInputListener();
+  public static abstract class TvView.TvInputCallback {
+    ctor public TvView.TvInputCallback();
     method public void onChannelRetuned(java.lang.String, android.net.Uri);
     method public void onConnectionFailed(java.lang.String);
     method public void onContentAllowed(java.lang.String);
@@ -27067,7 +27072,7 @@
     method public abstract android.service.media.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
     method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
     method public void setSessionToken(android.media.session.MediaSession.Token);
-    field public static final java.lang.String SERVICE_ACTION = "android.media.browse.MediaBrowserService";
+    field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
   }
 
   public static final class MediaBrowserService.BrowserRoot {
@@ -27423,11 +27428,12 @@
     ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener);
     ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener, java.lang.String);
     method public int addEarcon(java.lang.String, java.lang.String, int);
-    method public int addEarcon(java.lang.String, java.lang.String);
+    method public deprecated int addEarcon(java.lang.String, java.lang.String);
+    method public int addEarcon(java.lang.String, java.io.File);
     method public int addSpeech(java.lang.String, java.lang.String, int);
     method public int addSpeech(java.lang.CharSequence, java.lang.String, int);
     method public int addSpeech(java.lang.String, java.lang.String);
-    method public int addSpeech(java.lang.CharSequence, java.lang.String);
+    method public int addSpeech(java.lang.CharSequence, java.io.File);
     method public deprecated boolean areDefaultsEnforced();
     method public java.util.Set<java.util.Locale> getAvailableLanguages();
     method public java.lang.String getDefaultEngine();
@@ -27441,7 +27447,7 @@
     method public java.util.Set<android.speech.tts.Voice> getVoices();
     method public int isLanguageAvailable(java.util.Locale);
     method public boolean isSpeaking();
-    method public int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
+    method public int playEarcon(java.lang.String, int, android.os.Bundle, java.lang.String);
     method public deprecated int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
     method public int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
     method public deprecated int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>);
@@ -27454,10 +27460,10 @@
     method public int setSpeechRate(float);
     method public int setVoice(android.speech.tts.Voice);
     method public void shutdown();
-    method public int speak(java.lang.CharSequence, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
+    method public int speak(java.lang.CharSequence, int, android.os.Bundle, java.lang.String);
     method public deprecated int speak(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
     method public int stop();
-    method public int synthesizeToFile(java.lang.CharSequence, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String, java.lang.String);
+    method public int synthesizeToFile(java.lang.CharSequence, android.os.Bundle, java.io.File, java.lang.String);
     method public deprecated int synthesizeToFile(java.lang.String, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
     field public static final java.lang.String ACTION_TTS_QUEUE_PROCESSING_COMPLETED = "android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED";
     field public static final int ERROR = -1; // 0xffffffff
@@ -27530,15 +27536,15 @@
 
   public abstract class TextToSpeechService extends android.app.Service {
     ctor public TextToSpeechService();
-    method protected int isValidVoiceName(java.lang.String);
     method public android.os.IBinder onBind(android.content.Intent);
     method protected java.lang.String onGetDefaultVoiceNameFor(java.lang.String, java.lang.String, java.lang.String);
     method protected java.util.Set<java.lang.String> onGetFeaturesForLanguage(java.lang.String, java.lang.String, java.lang.String);
     method protected abstract java.lang.String[] onGetLanguage();
-    method protected java.util.List<android.speech.tts.Voice> onGetVoices();
+    method public java.util.List<android.speech.tts.Voice> onGetVoices();
     method protected abstract int onIsLanguageAvailable(java.lang.String, java.lang.String, java.lang.String);
+    method public int onIsValidVoiceName(java.lang.String);
     method protected abstract int onLoadLanguage(java.lang.String, java.lang.String, java.lang.String);
-    method protected int onLoadVoice(java.lang.String);
+    method public int onLoadVoice(java.lang.String);
     method protected abstract void onStop();
     method protected abstract void onSynthesizeText(android.speech.tts.SynthesisRequest, android.speech.tts.SynthesisCallback);
   }
@@ -27559,7 +27565,7 @@
     method public java.util.Locale getLocale();
     method public java.lang.String getName();
     method public int getQuality();
-    method public boolean getRequiresNetworkConnection();
+    method public boolean isNetworkConnectionRequired();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int LATENCY_HIGH = 400; // 0x190
     field public static final int LATENCY_LOW = 200; // 0xc8
@@ -28216,7 +28222,6 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
-    field public static final int ROUTE_ALL = 15; // 0xf
     field public static final int ROUTE_BLUETOOTH = 2; // 0x2
     field public static final int ROUTE_EARPIECE = 1; // 0x1
     field public static final int ROUTE_SPEAKER = 8; // 0x8
@@ -28229,17 +28234,19 @@
 
   public abstract class Conference {
     ctor public Conference(android.telecomm.PhoneAccountHandle);
-    method public boolean addConnection(android.telecomm.Connection);
-    method public void destroy();
+    method public final boolean addConnection(android.telecomm.Connection);
+    method public final void destroy();
     method public final int getCapabilities();
     method public final java.util.List<android.telecomm.Connection> getConnections();
-    method public final android.telecomm.PhoneAccountHandle getPhoneAccount();
+    method public final android.telecomm.PhoneAccountHandle getPhoneAccountHandle();
     method public final int getState();
     method public void onDisconnect();
     method public void onHold();
+    method public void onMerge();
     method public void onSeparate(android.telecomm.Connection);
+    method public void onSwap();
     method public void onUnhold();
-    method public void removeConnection(android.telecomm.Connection);
+    method public final void removeConnection(android.telecomm.Connection);
     method public final void setActive();
     method public final void setCapabilities(int);
     method public final void setDisconnected(int, java.lang.String);
@@ -28306,12 +28313,11 @@
   }
 
   public final class ConnectionRequest implements android.os.Parcelable {
-    ctor public ConnectionRequest(android.telecomm.PhoneAccountHandle, android.net.Uri, int, android.os.Bundle);
+    ctor public ConnectionRequest(android.telecomm.PhoneAccountHandle, android.net.Uri, android.os.Bundle);
     method public int describeContents();
     method public android.telecomm.PhoneAccountHandle getAccountHandle();
+    method public android.net.Uri getAddress();
     method public android.os.Bundle getExtras();
-    method public android.net.Uri getHandle();
-    method public int getHandlePresentation();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
   }
@@ -28390,13 +28396,13 @@
     method public static java.lang.String toString(int);
     field public static final int ADD_CALL = 16; // 0x10
     field public static final int ALL = 255; // 0xff
-    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 MANAGE_CONFERENCE = 128; // 0x80
+    field public static final int MERGE_CONFERENCE = 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 SUPPORT_HOLD = 2; // 0x2
-    field public static final int SWAP_CALLS = 8; // 0x8
+    field public static final int SWAP_CONFERENCE = 8; // 0x8
   }
 
   public class PropertyPresentation {
@@ -28408,7 +28414,7 @@
   }
 
   public final class RemoteConference {
-    method public final void addListener(android.telecomm.RemoteConference.Listener);
+    method public final void addCallback(android.telecomm.RemoteConference.Callback);
     method public void disconnect();
     method public final int getCallCapabilities();
     method public final java.util.List<android.telecomm.RemoteConnection> getConnections();
@@ -28416,13 +28422,13 @@
     method public java.lang.String getDisconnectMessage();
     method public final int getState();
     method public void hold();
-    method public final void removeListener(android.telecomm.RemoteConference.Listener);
+    method public final void removeCallback(android.telecomm.RemoteConference.Callback);
     method public void separate(android.telecomm.RemoteConnection);
     method public void unhold();
   }
 
-  public static abstract class RemoteConference.Listener {
-    ctor public RemoteConference.Listener();
+  public static abstract class RemoteConference.Callback {
+    ctor public RemoteConference.Callback();
     method public void onCapabilitiesChanged(android.telecomm.RemoteConference, int);
     method public void onConnectionAdded(android.telecomm.RemoteConference, android.telecomm.RemoteConnection);
     method public void onConnectionRemoved(android.telecomm.RemoteConference, android.telecomm.RemoteConnection);
@@ -28489,11 +28495,11 @@
   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 getIconResId();
     method public java.lang.CharSequence getLabel();
+    method public android.content.ComponentName getPackageName();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
   }
@@ -28513,17 +28519,17 @@
     method public void registerPhoneAccount(android.telecomm.PhoneAccount);
     method public void showInCallScreen(boolean);
     method public void unregisterPhoneAccount(android.telecomm.PhoneAccountHandle);
-    field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecomm.intent.action.CHANGE_PHONE_ACCOUNTS";
-    field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.intent.action.CONNECTION_SERVICE_CONFIGURE";
-    field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecomm.intent.action.SHOW_CALL_SETTINGS";
+    field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecomm.action.CHANGE_PHONE_ACCOUNTS";
+    field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecomm.action.CONNECTION_SERVICE_CONFIGURE";
+    field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecomm.action.SHOW_CALL_SETTINGS";
     field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
     field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
     field public static final java.lang.String EXTRA_CALL_BACK_NUMBER = "android.telecomm.extra.CALL_BACK_NUMBER";
     field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecomm.extra.CALL_DISCONNECT_CAUSE";
     field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecomm.extra.CALL_DISCONNECT_MESSAGE";
     field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecomm.extra.CONNECTION_SERVICE";
-    field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.intent.extra.PHONE_ACCOUNT_HANDLE";
-    field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.intent.extra.START_CALL_WITH_SPEAKERPHONE";
+    field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecomm.extra.PHONE_ACCOUNT_HANDLE";
+    field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecomm.extra.START_CALL_WITH_SPEAKERPHONE";
   }
 
 }
@@ -29002,10 +29008,7 @@
   }
 
   public class TelephonyManager {
-    method public void enableSimplifiedNetworkSettings(boolean);
-    method public void enableSimplifiedNetworkSettings(long, boolean);
     method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
-    method public int getCalculatedPreferredNetworkType();
     method public int getCallState();
     method public android.telephony.CellLocation getCellLocation();
     method public int getDataActivity();
@@ -29022,14 +29025,11 @@
     method public java.lang.String getNetworkOperatorName();
     method public int getNetworkType();
     method public int getPhoneType();
-    method public int getPreferredNetworkType();
     method public java.lang.String getSimCountryIso();
     method public java.lang.String getSimOperator();
     method public java.lang.String getSimOperatorName();
     method public java.lang.String getSimSerialNumber();
     method public int getSimState();
-    method public boolean getSimplifiedNetworkSettingsEnabled();
-    method public boolean getSimplifiedNetworkSettingsEnabled(long);
     method public java.lang.String getSubscriberId();
     method public java.lang.String getVoiceMailAlphaTag();
     method public java.lang.String getVoiceMailNumber();
@@ -29044,11 +29044,10 @@
     method public boolean isSmsCapable();
     method public void listen(android.telephony.PhoneStateListener, int);
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
-    method public boolean setCdmaSubscription(int);
+    method public boolean setGlobalPreferredNetworkType();
     method public void setLine1NumberForDisplay(java.lang.String, java.lang.String);
     method public void setLine1NumberForDisplay(long, java.lang.String, java.lang.String);
-    method public boolean setOperatorBrandOverride(java.lang.String, java.lang.String);
-    method public boolean setPreferredNetworkType(int);
+    method public boolean setOperatorBrandOverride(java.lang.String);
     field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
     field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
     field public static final int CALL_STATE_IDLE = 0; // 0x0
@@ -35899,8 +35898,8 @@
   public final class CursorAnchorInfo implements android.os.Parcelable {
     ctor public CursorAnchorInfo(android.os.Parcel);
     method public int describeContents();
-    method public android.graphics.RectF getCharacterRect(int);
-    method public int getCharacterRectFlags(int);
+    method public android.graphics.RectF getCharacterBounds(int);
+    method public int getCharacterBoundsFlags(int);
     method public java.lang.CharSequence getComposingText();
     method public int getComposingTextStart();
     method public float getInsertionMarkerBaseline();
@@ -35915,11 +35914,12 @@
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int FLAG_HAS_INVISIBLE_REGION = 2; // 0x2
     field public static final int FLAG_HAS_VISIBLE_REGION = 1; // 0x1
+    field public static final int FLAG_IS_RTL = 4; // 0x4
   }
 
   public static final class CursorAnchorInfo.Builder {
     ctor public CursorAnchorInfo.Builder();
-    method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float, int);
+    method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterBounds(int, float, float, float, float, int);
     method public android.view.inputmethod.CursorAnchorInfo build();
     method public void reset();
     method public android.view.inputmethod.CursorAnchorInfo.Builder setComposingText(int, java.lang.CharSequence);
@@ -37562,6 +37562,7 @@
     method public android.widget.CalendarView getCalendarView();
     method public boolean getCalendarViewShown();
     method public int getDayOfMonth();
+    method public int getFirstDayOfWeek();
     method public long getMaxDate();
     method public long getMinDate();
     method public int getMonth();
@@ -37569,6 +37570,7 @@
     method public int getYear();
     method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
     method public void setCalendarViewShown(boolean);
+    method public void setFirstDayOfWeek(int);
     method public void setMaxDate(long);
     method public void setMinDate(long);
     method public void setSpinnersShown(boolean);
diff --git a/api/removed.txt b/api/removed.txt
index 0aa6d54..3c16276 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -1,19 +1,3 @@
-package android {
-
-  public static final class R.attr {
-    field public static final int __removed1 = 16843955; // 0x10104b3
-  }
-
-}
-
-package android.app {
-
-  public class KeyguardManager {
-    method public android.content.Intent getConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
-  }
-
-}
-
 package android.media {
 
   public class AudioFormat {
@@ -61,6 +45,8 @@
   }
 
   public final class CursorAnchorInfo implements android.os.Parcelable {
+    method public android.graphics.RectF getCharacterRect(int);
+    method public int getCharacterRectFlags(int);
     method public boolean isInsertionMarkerClipped();
     field public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; // 0x1
     field public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; // 0x3
@@ -71,6 +57,7 @@
   }
 
   public static final class CursorAnchorInfo.Builder {
+    method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float, int);
     method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, boolean);
   }
 
@@ -86,11 +73,3 @@
 
 }
 
-package com.android.internal {
-
-  public static final class R.attr {
-    field public static final int __removed1 = 16843955; // 0x10104b3
-  }
-
-}
-
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 9156eeb..7c13dbe 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -504,6 +504,10 @@
         mStarted = true;
         mPaused = false;
 
+        for (Node node : mNodes) {
+            node.animation.setAllowRunningAsynchronously(false);
+        }
+
         if (mDuration >= 0) {
             // If the duration was set on this AnimatorSet, pass it along to all child animations
             for (Node node : mNodes) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 3e03893..9486a72 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2656,17 +2656,24 @@
 
         /**
          * Start an activity in this task.  Brings the task to the foreground.  If this task
-         * is not currently active (that is, its id < 0), then the activity being started
-         * needs to be started as a new task and the Intent's ComponentName must match the
-         * base ComponenentName of the recent task entry.  Otherwise, the activity being
-         * started must <b>not</b> be launched as a new task -- not through explicit intent
-         * flags nor implicitly as the singleTask or singleInstance launch modes.
+         * is not currently active (that is, its id < 0), then a new activity for the given
+         * Intent will be launched as the root of the task and the task brought to the
+         * foreground.  Otherwise, if this task is currently active and the Intent does not specify
+         * an activity to launch in a new task, then a new activity for the given Intent will
+         * be launched on top of the task and the task brought to the foreground.  If this
+         * task is currently active and the Intent specifies {@link Intent#FLAG_ACTIVITY_NEW_TASK}
+         * or would otherwise be launched in to a new task, then the activity not launched but
+         * this task be brought to the foreground and a new intent delivered to the top
+         * activity if appropriate.
          *
-         * <p>See {@link Activity#startActivity(android.content.Intent, android.os.Bundle)
-         * Activity.startActivity} for more information.</p>
+         * <p>In other words, you generally want to use an Intent here that does not specify
+         * {@link Intent#FLAG_ACTIVITY_NEW_TASK} or {@link Intent#FLAG_ACTIVITY_NEW_DOCUMENT},
+         * and let the system do the right thing.</p>
          *
          * @param intent The Intent describing the new activity to be launched on the task.
          * @param options Optional launch options.
+         *
+         * @see Activity#startActivity(android.content.Intent, android.os.Bundle)
          */
         public void startActivity(Context context, Intent intent, Bundle options) {
             ActivityThread thread = ActivityThread.currentActivityThread();
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 1f7e450..394b183 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -509,8 +509,7 @@
         case ACTIVITY_PAUSED_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
-            PersistableBundle persistentState = data.readPersistableBundle();
-            activityPaused(token, persistentState);
+            activityPaused(token);
             reply.writeNoException();
             return true;
         }
@@ -2829,13 +2828,12 @@
         data.recycle();
         reply.recycle();
     }
-    public void activityPaused(IBinder token, PersistableBundle persistentState) throws RemoteException
+    public void activityPaused(IBinder token) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
-        data.writePersistableBundle(persistentState);
         mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 9dd4605..ffffb6c 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -84,13 +84,13 @@
      * Initial width of the animation.
      * @hide
      */
-    public static final String KEY_ANIM_START_WIDTH = "android:animStartWidth";
+    public static final String KEY_ANIM_WIDTH = "android:animWidth";
 
     /**
      * Initial height of the animation.
      * @hide
      */
-    public static final String KEY_ANIM_START_HEIGHT = "android:animStartHeight";
+    public static final String KEY_ANIM_HEIGHT = "android:animHeight";
 
     /**
      * Callback for when animation is started.
@@ -140,8 +140,8 @@
     private Bitmap mThumbnail;
     private int mStartX;
     private int mStartY;
-    private int mStartWidth;
-    private int mStartHeight;
+    private int mWidth;
+    private int mHeight;
     private IRemoteCallback mAnimationStartedListener;
     private ResultReceiver mTransitionReceiver;
     private boolean mIsReturning;
@@ -238,13 +238,13 @@
      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
      * @param startX The x starting location of the new activity, relative to <var>source</var>.
      * @param startY The y starting location of the activity, relative to <var>source</var>.
-     * @param startWidth The initial width of the new activity.
-     * @param startHeight The initial height of the new activity.
+     * @param width The initial width of the new activity.
+     * @param height The initial height of the new activity.
      * @return Returns a new ActivityOptions object that you can use to
      * supply these options as the options Bundle when starting an activity.
      */
     public static ActivityOptions makeScaleUpAnimation(View source,
-            int startX, int startY, int startWidth, int startHeight) {
+            int startX, int startY, int width, int height) {
         ActivityOptions opts = new ActivityOptions();
         opts.mPackageName = source.getContext().getPackageName();
         opts.mAnimationType = ANIM_SCALE_UP;
@@ -252,8 +252,8 @@
         source.getLocationOnScreen(pts);
         opts.mStartX = pts[0] + startX;
         opts.mStartY = pts[1] + startY;
-        opts.mStartWidth = startWidth;
-        opts.mStartHeight = startHeight;
+        opts.mWidth = width;
+        opts.mHeight = height;
         return opts;
     }
 
@@ -359,9 +359,10 @@
      * @hide
      */
     public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source,
-            Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
-        return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener,
-                true);
+            Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
+            OnAnimationStartedListener listener) {
+        return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
+                targetWidth, targetHeight, listener, true);
     }
 
     /**
@@ -382,13 +383,15 @@
      * @hide
      */
     public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
-            Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
-        return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener,
-                false);
+            Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
+            OnAnimationStartedListener listener) {
+        return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
+                targetWidth, targetHeight, listener, false);
     }
 
     private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail,
-            int startX, int startY, OnAnimationStartedListener listener, boolean scaleUp) {
+            int startX, int startY, int targetWidth, int targetHeight,
+            OnAnimationStartedListener listener, boolean scaleUp) {
         ActivityOptions opts = new ActivityOptions();
         opts.mPackageName = source.getContext().getPackageName();
         opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP :
@@ -398,6 +401,8 @@
         source.getLocationOnScreen(pts);
         opts.mStartX = pts[0] + startX;
         opts.mStartY = pts[1] + startY;
+        opts.mWidth = targetWidth;
+        opts.mHeight = targetHeight;
         opts.setOnAnimationStartedListener(source.getHandler(), listener);
         return opts;
     }
@@ -543,8 +548,8 @@
             case ANIM_SCALE_UP:
                 mStartX = opts.getInt(KEY_ANIM_START_X, 0);
                 mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
-                mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
-                mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
+                mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
+                mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
                 break;
 
             case ANIM_THUMBNAIL_SCALE_UP:
@@ -554,6 +559,8 @@
                 mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL);
                 mStartX = opts.getInt(KEY_ANIM_START_X, 0);
                 mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
+                mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
+                mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
                 mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
                         opts.getBinder(KEY_ANIM_START_LISTENER));
                 break;
@@ -605,13 +612,13 @@
     }
 
     /** @hide */
-    public int getStartWidth() {
-        return mStartWidth;
+    public int getWidth() {
+        return mWidth;
     }
 
     /** @hide */
-    public int getStartHeight() {
-        return mStartHeight;
+    public int getHeight() {
+        return mHeight;
     }
 
     /** @hide */
@@ -690,8 +697,8 @@
             case ANIM_SCALE_UP:
                 mStartX = otherOptions.mStartX;
                 mStartY = otherOptions.mStartY;
-                mStartWidth = otherOptions.mStartWidth;
-                mStartHeight = otherOptions.mStartHeight;
+                mWidth = otherOptions.mWidth;
+                mHeight = otherOptions.mHeight;
                 if (mAnimationStartedListener != null) {
                     try {
                         mAnimationStartedListener.sendResult(null);
@@ -707,6 +714,8 @@
                 mThumbnail = otherOptions.mThumbnail;
                 mStartX = otherOptions.mStartX;
                 mStartY = otherOptions.mStartY;
+                mWidth = otherOptions.mWidth;
+                mHeight = otherOptions.mHeight;
                 if (mAnimationStartedListener != null) {
                     try {
                         mAnimationStartedListener.sendResult(null);
@@ -755,8 +764,8 @@
             case ANIM_SCALE_UP:
                 b.putInt(KEY_ANIM_START_X, mStartX);
                 b.putInt(KEY_ANIM_START_Y, mStartY);
-                b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
-                b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
+                b.putInt(KEY_ANIM_WIDTH, mWidth);
+                b.putInt(KEY_ANIM_HEIGHT, mHeight);
                 break;
             case ANIM_THUMBNAIL_SCALE_UP:
             case ANIM_THUMBNAIL_SCALE_DOWN:
@@ -765,6 +774,8 @@
                 b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
                 b.putInt(KEY_ANIM_START_X, mStartX);
                 b.putInt(KEY_ANIM_START_Y, mStartY);
+                b.putInt(KEY_ANIM_WIDTH, mWidth);
+                b.putInt(KEY_ANIM_HEIGHT, mHeight);
                 b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
                         != null ? mAnimationStartedListener.asBinder() : null);
                 break;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4f2a3bc..3a39900 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -563,11 +563,11 @@
         }
 
         public final void schedulePauseActivity(IBinder token, boolean finished,
-                boolean userLeaving, int configChanges) {
+                boolean userLeaving, int configChanges, boolean dontReport) {
             sendMessage(
                     finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                     token,
-                    (userLeaving ? 1 : 0),
+                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
                     configChanges);
         }
 
@@ -1283,13 +1283,15 @@
                 } break;
                 case PAUSE_ACTIVITY:
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
-                    handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
+                    handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
+                            (msg.arg1&2) != 0);
                     maybeSnapshot();
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
                 case PAUSE_ACTIVITY_FINISHING:
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
-                    handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
+                    handlePauseActivity((IBinder)msg.obj, true, (msg.arg1&1) != 0, msg.arg2,
+                            (msg.arg1&1) != 0);
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
                 case STOP_ACTIVITY_SHOW:
@@ -3142,7 +3144,7 @@
     }
 
     private void handlePauseActivity(IBinder token, boolean finished,
-            boolean userLeaving, int configChanges) {
+            boolean userLeaving, int configChanges, boolean dontReport) {
         ActivityClientRecord r = mActivities.get(token);
         if (r != null) {
             //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
@@ -3159,9 +3161,11 @@
             }
 
             // Tell the activity manager we have paused.
-            try {
-                ActivityManagerNative.getDefault().activityPaused(token, r.persistentState);
-            } catch (RemoteException ex) {
+            if (!dontReport) {
+                try {
+                    ActivityManagerNative.getDefault().activityPaused(token);
+                } catch (RemoteException ex) {
+                }
             }
             mSomeActivitiesChanged = true;
         }
@@ -4283,6 +4287,8 @@
             AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
         }
 
+        Message.updateCheckRecycle(data.appInfo.targetSdkVersion);
+
         /*
          * Before spawning a new process, reset the time zone to be the system time zone.
          * This needs to be done because the system time zone could have changed after the
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 9e80a4b..9f49194 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -205,6 +205,7 @@
     private boolean mIsStartingTransition;
     private ArrayList<GhostViewListeners> mGhostViewListeners =
             new ArrayList<GhostViewListeners>();
+    private ArrayMap<View, Float> mOriginalAlphas = new ArrayMap<View, Float>();
 
     public ActivityTransitionCoordinator(Window window,
             ArrayList<String> allSharedElementNames,
@@ -580,6 +581,7 @@
         mWindow = null;
         mSharedElements.clear();
         mTransitioningViews.clear();
+        mOriginalAlphas.clear();
         mResultReceiver = null;
         mPendingTransition = null;
         mListener = null;
@@ -589,10 +591,27 @@
         return getWindow().getTransitionBackgroundFadeDuration();
     }
 
-    protected static void setTransitionAlpha(ArrayList<View> views, float alpha) {
+    protected void hideViews(ArrayList<View> views) {
         int count = views.size();
         for (int i = 0; i < count; i++) {
-            views.get(i).setTransitionAlpha(alpha);
+            View view = views.get(i);
+            if (!mOriginalAlphas.containsKey(view)) {
+                mOriginalAlphas.put(view, view.getAlpha());
+            }
+            view.setAlpha(0f);
+            view.setTransitionAlpha(0f);
+        }
+    }
+
+    protected void showViews(ArrayList<View> views) {
+        int count = views.size();
+        for (int i = 0; i < count; i++) {
+            View view = views.get(i);
+            Float alpha = mOriginalAlphas.remove(view);
+            if (alpha != null) {
+                view.setAlpha(alpha);
+                view.setTransitionAlpha(1f);
+            }
         }
     }
 
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 9cd6d49..404268c 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1693,7 +1693,7 @@
         if (dr == null) {
             dr = itemInfo.loadDefaultIcon(this);
         }
-        return getUserBadgedDrawableForDensity(dr, new UserHandle(mContext.getUserId()), null, 0);
+        return getUserBadgedIcon(dr, new UserHandle(mContext.getUserId()));
     }
 
     private Drawable getBadgedDrawable(Drawable drawable, Drawable badgeDrawable,
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 63e8707..0123e16 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -78,7 +78,8 @@
             boolean finished = data.readInt() != 0;
             boolean userLeaving = data.readInt() != 0;
             int configChanges = data.readInt();
-            schedulePauseActivity(b, finished, userLeaving, configChanges);
+            boolean dontReport = data.readInt() != 0;
+            schedulePauseActivity(b, finished, userLeaving, configChanges, dontReport);
             return true;
         }
 
@@ -689,13 +690,14 @@
     }
     
     public final void schedulePauseActivity(IBinder token, boolean finished,
-            boolean userLeaving, int configChanges) throws RemoteException {
+            boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(token);
         data.writeInt(finished ? 1 : 0);
         data.writeInt(userLeaving ? 1 :0);
         data.writeInt(configChanges);
+        data.writeInt(dontReport ? 1 : 0);
         mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
         data.recycle();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 91a0aed..cc5c643 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2121,7 +2121,9 @@
     public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
             throws NameNotFoundException {
         final boolean restricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
-        if (packageName.equals("system") || packageName.equals("android")) {
+        if ((packageName.equals("system") || packageName.equals("android"))
+                && user.getIdentifier() == UserHandle.getUserId(
+                        mPackageInfo.getApplicationInfo().uid)) {
             return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
                     user, restricted, mDisplay, mOverrideConfiguration);
         }
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index f432c49..f38c108 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -112,9 +112,9 @@
     protected void viewsReady(ArrayMap<String, View> sharedElements) {
         super.viewsReady(sharedElements);
         mIsReadyForTransition = true;
-        setTransitionAlpha(mSharedElements, 0);
+        hideViews(mSharedElements);
         if (getViewsTransition() != null) {
-            setTransitionAlpha(mTransitioningViews, 0);
+            hideViews(mTransitioningViews);
         }
         if (mIsReturning) {
             sendSharedElementDestination();
@@ -240,7 +240,7 @@
         if (!mIsCanceled) {
             mIsCanceled = true;
             if (getViewsTransition() == null || mIsViewsTransitionStarted) {
-                setTransitionAlpha(mSharedElements, 1);
+                showViews(mSharedElements);
             } else {
                 mTransitioningViews.addAll(mSharedElements);
             }
@@ -300,7 +300,7 @@
         // Now start shared element transition
         ArrayList<View> sharedElementSnapshots = createSnapshots(sharedElementState,
                 mSharedElementNames);
-        setTransitionAlpha(mSharedElements, 1);
+        showViews(mSharedElements);
         scheduleSetSharedElementEnd(sharedElementSnapshots);
         ArrayList<SharedElementOriginalState> originalImageViewState =
                 setSharedElementState(sharedElementState, sharedElementSnapshots);
@@ -411,7 +411,7 @@
                     @Override
                     public void onTransitionStart(Transition transition) {
                         mEnterViewsTransition = transition;
-                        setTransitionAlpha(mTransitioningViews, 1);
+                        showViews(mTransitioningViews);
                         super.onTransitionStart(transition);
                     }
 
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index a59a927..982bbc4 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -126,8 +126,8 @@
     }
 
     public void resetViews() {
-        setTransitionAlpha(mTransitioningViews, 1);
-        setTransitionAlpha(mSharedElements, 1);
+        showViews(mTransitioningViews);
+        showViews(mSharedElements);
         mIsHidden = true;
         if (!mIsReturning && getDecor() != null) {
             getDecor().suppressLayout(false);
@@ -187,7 +187,7 @@
     private void hideSharedElements() {
         moveSharedElementsFromOverlay();
         if (!mIsHidden) {
-            setTransitionAlpha(mSharedElements, 0);
+            hideViews(mSharedElements);
         }
         mSharedElementsHidden = true;
         finishIfNecessary();
@@ -296,7 +296,7 @@
                     transition.removeListener(this);
                     exitTransitionComplete();
                     if (mIsHidden) {
-                        setTransitionAlpha(mTransitioningViews, 1);
+                        showViews(mTransitioningViews);
                     }
                     if (mSharedElementBundle != null) {
                         delayCancel();
@@ -323,7 +323,7 @@
                     transition.removeListener(this);
                     sharedElementTransitionComplete();
                     if (mIsHidden) {
-                        setTransitionAlpha(mSharedElements, 1);
+                        showViews(mSharedElements);
                     }
                 }
             });
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 99428e8..9483680 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -111,7 +111,7 @@
     public void activityResumed(IBinder token) throws RemoteException;
     public void activityIdle(IBinder token, Configuration config,
             boolean stopProfiling) throws RemoteException;
-    public void activityPaused(IBinder token, PersistableBundle persistentState) throws RemoteException;
+    public void activityPaused(IBinder token) throws RemoteException;
     public void activityStopped(IBinder token, Bundle state,
             PersistableBundle persistentState, CharSequence description) throws RemoteException;
     public void activitySlept(IBinder token) throws RemoteException;
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index a7546d9..f53075c 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -49,7 +49,7 @@
  */
 public interface IApplicationThread extends IInterface {
     void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,
-            int configChanges) throws RemoteException;
+            int configChanges, boolean dontReport) throws RemoteException;
     void scheduleStopActivity(IBinder token, boolean showWindow,
             int configChanges) throws RemoteException;
     void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index e055237..cc9aed8 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -56,13 +56,6 @@
     public static final String EXTRA_DESCRIPTION = "android.app.extra.DESCRIPTION";
 
     /**
-     * @removed
-     */
-    public Intent getConfirmDeviceCredentialIntent(CharSequence title, CharSequence description) {
-        return createConfirmDeviceCredentialIntent(title, description);
-    }
-
-    /**
      * Get an intent to prompt the user to confirm credentials (pin, pattern or password)
      * for the current user of the device. The caller is expected to launch this activity using
      * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 112fc82..926a348 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -441,13 +441,13 @@
      * Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from a
      * managed profile to its parent.
      */
-    public static int FLAG_PARENT_CAN_ACCESS_MANAGED = 0x0001;
+    public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 0x0001;
 
     /**
      * Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from the
      * parent to its managed profile.
      */
-    public static int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002;
+    public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002;
 
     /**
      * Return true if the given administrator component is currently
diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java
index c7bfae9..ff0db9a 100644
--- a/core/java/android/bluetooth/le/AdvertiseData.java
+++ b/core/java/android/bluetooth/le/AdvertiseData.java
@@ -119,8 +119,8 @@
         }
         AdvertiseData other = (AdvertiseData) obj;
         return Objects.equals(mServiceUuids, other.mServiceUuids) &&
-                Utils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) &&
-                Utils.equals(mServiceData, other.mServiceData) &&
+                BluetoothLeUtils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) &&
+                BluetoothLeUtils.equals(mServiceData, other.mServiceData) &&
                         mIncludeDeviceName == other.mIncludeDeviceName &&
                         mIncludeTxPowerLevel == other.mIncludeTxPowerLevel;
     }
@@ -128,8 +128,8 @@
     @Override
     public String toString() {
         return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerSpecificData="
-                + Utils.toString(mManufacturerSpecificData) + ", mServiceData="
-                + Utils.toString(mServiceData)
+                + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData="
+                + BluetoothLeUtils.toString(mServiceData)
                 + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName="
                 + mIncludeDeviceName + "]";
     }
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 3568f26..d468508 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -107,7 +107,7 @@
             AdvertiseData advertiseData, AdvertiseData scanResponse,
             final AdvertiseCallback callback) {
         synchronized (mLeAdvertisers) {
-            checkAdapterState();
+            BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
             if (callback == null) {
                 throw new IllegalArgumentException("callback cannot be null");
             }
@@ -150,7 +150,7 @@
      */
     public void stopAdvertising(final AdvertiseCallback callback) {
         synchronized (mLeAdvertisers) {
-            checkAdapterState();
+            BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
             if (callback == null) {
                 throw new IllegalArgumentException("callback cannot be null");
             }
@@ -265,9 +265,18 @@
                 }
                 if (mClientIf > 0 && mIsAdvertising) {
                     mLeAdvertisers.put(mAdvertiseCallback, this);
-                } else {
+                } else if (mClientIf <= 0) {
+                    // Post internal error if registration failed.
                     postStartFailure(mAdvertiseCallback,
                             AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
+                } else {
+                    // Unregister application if it's already registered but advertise failed.
+                    try {
+                        mBluetoothGatt.unregisterClient(mClientIf);
+                        mClientIf = -1;
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "remote exception when unregistering", e);
+                    }
                 }
             }
         }
@@ -342,13 +351,6 @@
         }
     }
 
-    // TODO: move this api to a common util class.
-    private void checkAdapterState() {
-        if (mBluetoothAdapter.getState() != mBluetoothAdapter.STATE_ON) {
-            throw new IllegalStateException("BT Adapter is not turned ON");
-        }
-    }
-
     private void postStartFailure(final AdvertiseCallback callback, final int error) {
         mHandler.post(new Runnable() {
             @Override
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index e1d4bbd2..a57c3ca 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -80,11 +80,10 @@
      * @throws IllegalArgumentException If {@code callback} is null.
      */
     public void startScan(final ScanCallback callback) {
-        checkAdapterState();
         if (callback == null) {
             throw new IllegalArgumentException("callback is null");
         }
-        this.startScan(null, new ScanSettings.Builder().build(), callback);
+        startScan(null, new ScanSettings.Builder().build(), callback);
     }
 
     /**
@@ -104,7 +103,7 @@
 
     private void startScan(List<ScanFilter> filters, ScanSettings settings,
             final ScanCallback callback, List<List<ResultStorageDescriptor>> resultStorages) {
-        checkAdapterState();
+        BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
         if (settings == null || callback == null) {
             throw new IllegalArgumentException("settings or callback is null");
         }
@@ -142,7 +141,7 @@
      * @param callback
      */
     public void stopScan(ScanCallback callback) {
-        checkAdapterState();
+        BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
         synchronized (mLeScanClients) {
             BleScanCallbackWrapper wrapper = mLeScanClients.remove(callback);
             if (wrapper == null) {
@@ -162,7 +161,7 @@
      *            used to start scan.
      */
     public void flushPendingScanResults(ScanCallback callback) {
-        checkAdapterState();
+        BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
         if (callback == null) {
             throw new IllegalArgumentException("callback cannot be null!");
         }
@@ -373,13 +372,6 @@
         }
     }
 
-    // TODO: move this api to a common util class.
-    private void checkAdapterState() {
-        if (mBluetoothAdapter.getState() != mBluetoothAdapter.STATE_ON) {
-            throw new IllegalStateException("BT Adapter is not turned ON");
-        }
-    }
-
     private void postCallbackError(final ScanCallback callback, final int errorCode) {
         mHandler.post(new Runnable() {
             @Override
diff --git a/core/java/android/bluetooth/le/Utils.java b/core/java/android/bluetooth/le/BluetoothLeUtils.java
similarity index 87%
rename from core/java/android/bluetooth/le/Utils.java
rename to core/java/android/bluetooth/le/BluetoothLeUtils.java
index ccdae69..4916bd9 100644
--- a/core/java/android/bluetooth/le/Utils.java
+++ b/core/java/android/bluetooth/le/BluetoothLeUtils.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth.le;
 
+import android.bluetooth.BluetoothAdapter;
 import android.util.SparseArray;
 
 import java.util.Arrays;
@@ -29,7 +30,7 @@
  *
  * @hide
  */
-public class Utils {
+public class BluetoothLeUtils {
 
     /**
      * Returns a string composed from a {@link SparseArray}.
@@ -123,4 +124,17 @@
         }
         return true;
     }
+
+    /**
+     * Ensure Bluetooth is turned on.
+     *
+     * @throws IllegalStateException If {@code adapter} is null or Bluetooth state is not
+     *             {@link BluetoothAdapter#STATE_ON}.
+     */
+    static void checkAdapterStateOn(BluetoothAdapter adapter) {
+        if (adapter == null || adapter.getState() != BluetoothAdapter.STATE_ON) {
+            throw new IllegalStateException("BT Adapter is not turned ON");
+        }
+    }
+
 }
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index 2f3d06f..f802e8d 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -268,8 +268,8 @@
     @Override
     public String toString() {
         return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids
-                + ", mManufacturerSpecificData=" + Utils.toString(mManufacturerSpecificData)
-                + ", mServiceData=" + Utils.toString(mServiceData)
+                + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString(mManufacturerSpecificData)
+                + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData)
                 + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]";
     }
 
diff --git a/core/java/android/content/IRestrictionsManager.aidl b/core/java/android/content/IRestrictionsManager.aidl
index 495ac2e..db9146f 100644
--- a/core/java/android/content/IRestrictionsManager.aidl
+++ b/core/java/android/content/IRestrictionsManager.aidl
@@ -30,5 +30,5 @@
     void requestPermission(in String packageName, in String requestType, in String requestId,
             in PersistableBundle requestData);
     void notifyPermissionResponse(in String packageName, in PersistableBundle response);
-    Intent getLocalApprovalIntent();
+    Intent createLocalApprovalIntent();
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 51a58d1..ff9f6ab 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1213,6 +1213,13 @@
             = "android.intent.extra.ASSIST_CONTEXT";
 
     /**
+     * An optional field on {@link #ACTION_ASSIST} suggesting that the user will likely use a
+     * keyboard as the primary input device for assistance.
+     */
+    public static final String EXTRA_ASSIST_INPUT_HINT_KEYBOARD =
+            "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
+
+    /**
      * Activity Action: List all available applications
      * <p>Input: Nothing.
      * <p>Output: nothing.
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index 849df55..21a6a0d 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -155,7 +155,7 @@
      * The intent must contain {@link #EXTRA_REQUEST_BUNDLE} as an extra and the bundle must
      * contain at least {@link #REQUEST_KEY_MESSAGE} for the activity to display.
      * <p>
-     * @see #getLocalApprovalIntent()
+     * @see #createLocalApprovalIntent()
      */
     public static final String ACTION_REQUEST_LOCAL_APPROVAL =
             "android.content.action.REQUEST_LOCAL_APPROVAL";
@@ -473,10 +473,10 @@
         }
     }
 
-    public Intent getLocalApprovalIntent() {
+    public Intent createLocalApprovalIntent() {
         try {
             if (mService != null) {
-                return mService.getLocalApprovalIntent();
+                return mService.createLocalApprovalIntent();
             }
         } catch (RemoteException re) {
             Log.w(TAG, "Couldn't reach service");
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index dbf49c5..8d3126d 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -255,16 +255,22 @@
      * Bit in {@link #flags}: If set, a task rooted at this activity will have its
      * baseIntent replaced by the activity immediately above this. Each activity may further
      * relinquish its identity to the activity above it using this flag. Set from the
-     * android.R.attr#relinquishTaskIdentity attribute.
+     * {@link android.R.attr#relinquishTaskIdentity} attribute.
      */
     public static final int FLAG_RELINQUISH_TASK_IDENTITY = 0x1000;
     /**
      * Bit in {@link #flags} indicating that tasks started with this activity are to be
      * removed from the recent list of tasks when the last activity in the task is finished.
-     * {@link android.R.attr#autoRemoveFromRecents}
+     * Corresponds to {@link android.R.attr#autoRemoveFromRecents}
      */
     public static final int FLAG_AUTO_REMOVE_FROM_RECENTS = 0x2000;
     /**
+     * Bit in {@link #flags} indicating that this activity can start is creation/resume
+     * while the previous activity is still pausing.  Corresponds to
+     * {@link android.R.attr#resumeWhilePausing}
+     */
+    public static final int FLAG_RESUME_WHILE_PAUSING = 0x4000;
+    /**
      * @hide Bit in {@link #flags}: If set, this component will only be seen
      * by the primary user.  Only works with broadcast receivers.  Set from the
      * android.R.attr#primaryUserOnly attribute.
diff --git a/core/java/android/content/pm/IPackageInstallerCallback.aidl b/core/java/android/content/pm/IPackageInstallerCallback.aidl
index fe98ee7..974eb1e 100644
--- a/core/java/android/content/pm/IPackageInstallerCallback.aidl
+++ b/core/java/android/content/pm/IPackageInstallerCallback.aidl
@@ -20,8 +20,7 @@
 oneway interface IPackageInstallerCallback {
     void onSessionCreated(int sessionId);
     void onSessionBadgingChanged(int sessionId);
-    void onSessionOpened(int sessionId);
+    void onSessionActiveChanged(int sessionId, boolean active);
     void onSessionProgressChanged(int sessionId, float progress);
-    void onSessionClosed(int sessionId);
     void onSessionFinished(int sessionId, boolean success);
 }
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 7c34a65..06d4c4a 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -285,6 +285,9 @@
      *
      * @throws IOException if parameters were unsatisfiable, such as lack of
      *             disk space or unavailable media.
+     * @throws SecurityException when installation services are unavailable,
+     *             such as when called from a restricted user.
+     * @throws IllegalArgumentException when {@link SessionParams} is invalid.
      * @return positive, non-zero unique ID that represents the created session.
      *         This ID remains consistent across device reboots until the
      *         session is finalized. IDs are not reused during a given boot.
@@ -303,10 +306,18 @@
     /**
      * Open an existing session to actively perform work. To succeed, the caller
      * must be the owner of the install session.
+     *
+     * @throws IOException if parameters were unsatisfiable, such as lack of
+     *             disk space or unavailable media.
+     * @throws SecurityException when the caller does not own the session, or
+     *             the session is invalid.
      */
-    public @NonNull Session openSession(int sessionId) {
+    public @NonNull Session openSession(int sessionId) throws IOException {
         try {
             return new Session(mInstaller.openSession(sessionId));
+        } catch (RuntimeException e) {
+            ExceptionUtils.maybeUnwrapIOException(e);
+            throw e;
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
@@ -316,6 +327,9 @@
      * Update the icon representing the app being installed in a specific
      * session. This should be roughly
      * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions.
+     *
+     * @throws SecurityException when the caller does not own the session, or
+     *             the session is invalid.
      */
     public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) {
         try {
@@ -328,6 +342,9 @@
     /**
      * Update the label representing the app being installed in a specific
      * session.
+     *
+     * @throws SecurityException when the caller does not own the session, or
+     *             the session is invalid.
      */
     public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) {
         try {
@@ -338,6 +355,15 @@
         }
     }
 
+    /**
+     * Completely abandon the given session, destroying all staged data and
+     * rendering it invalid. Abandoned sessions will be reported to
+     * {@link SessionCallback} listeners as failures. This is equivalent to
+     * opening the session and calling {@link Session#abandon()}.
+     *
+     * @throws SecurityException when the caller does not own the session, or
+     *             the session is invalid.
+     */
     public void abandonSession(int sessionId) {
         try {
             mInstaller.abandonSession(sessionId);
@@ -347,7 +373,11 @@
     }
 
     /**
-     * Return details for a specific session.
+     * Return details for a specific session. No special permissions are
+     * required to retrieve these details.
+     *
+     * @return details for the requested session, or {@code null} if the session
+     *         does not exist.
      */
     public @Nullable SessionInfo getSessionInfo(int sessionId) {
         try {
@@ -358,12 +388,12 @@
     }
 
     /**
-     * Return list of all active install sessions, regardless of the installer.
+     * Return list of all known install sessions, regardless of the installer.
      */
     public @NonNull List<SessionInfo> getAllSessions() {
         final ApplicationInfo info = mContext.getApplicationInfo();
         if ("com.google.android.googlequicksearchbox".equals(info.packageName)
-                && info.versionCode <= 300400070) {
+                && info.versionCode <= 300400110) {
             Log.d(TAG, "Ignoring callback request from old prebuilt");
             return Collections.EMPTY_LIST;
         }
@@ -376,7 +406,7 @@
     }
 
     /**
-     * Return list of all install sessions owned by the calling app.
+     * Return list of all known install sessions owned by the calling app.
      */
     public @NonNull List<SessionInfo> getMySessions() {
         try {
@@ -436,27 +466,32 @@
         public abstract void onBadgingChanged(int sessionId);
 
         /**
-         * Session has been opened. A session is usually opened when the
-         * installer is actively writing data.
+         * Active state for session has been changed.
+         * <p>
+         * A session is considered active whenever there is ongoing forward
+         * progress being made, such as the installer holding an open
+         * {@link Session} instance while streaming data into place, or the
+         * system optimizing code as the result of
+         * {@link Session#commit(IntentSender)}.
+         * <p>
+         * If the installer closes the {@link Session} without committing, the
+         * session is considered inactive until the installer opens the session
+         * again.
          */
-        public abstract void onOpened(int sessionId);
+        public abstract void onActiveChanged(int sessionId, boolean active);
 
         /**
          * Progress for given session has been updated.
          * <p>
          * Note that this progress may not directly correspond to the value
-         * reported by {@link PackageInstaller.Session#setProgress(float)}, as
-         * the system may carve out a portion of the overall progress to
-         * represent its own internal installation work.
+         * reported by
+         * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
+         * system may carve out a portion of the overall progress to represent
+         * its own internal installation work.
          */
         public abstract void onProgressChanged(int sessionId, float progress);
 
         /**
-         * Session has been closed.
-         */
-        public abstract void onClosed(int sessionId);
-
-        /**
          * Session has completely finished, either with success or failure.
          */
         public abstract void onFinished(int sessionId, boolean success);
@@ -467,10 +502,9 @@
             Handler.Callback {
         private static final int MSG_SESSION_CREATED = 1;
         private static final int MSG_SESSION_BADGING_CHANGED = 2;
-        private static final int MSG_SESSION_OPENED = 3;
+        private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
         private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
-        private static final int MSG_SESSION_CLOSED = 5;
-        private static final int MSG_SESSION_FINISHED = 6;
+        private static final int MSG_SESSION_FINISHED = 5;
 
         final SessionCallback mCallback;
         final Handler mHandler;
@@ -482,24 +516,23 @@
 
         @Override
         public boolean handleMessage(Message msg) {
+            final int sessionId = msg.arg1;
             switch (msg.what) {
                 case MSG_SESSION_CREATED:
-                    mCallback.onCreated(msg.arg1);
+                    mCallback.onCreated(sessionId);
                     return true;
                 case MSG_SESSION_BADGING_CHANGED:
-                    mCallback.onBadgingChanged(msg.arg1);
+                    mCallback.onBadgingChanged(sessionId);
                     return true;
-                case MSG_SESSION_OPENED:
-                    mCallback.onOpened(msg.arg1);
+                case MSG_SESSION_ACTIVE_CHANGED:
+                    final boolean active = msg.arg2 != 0;
+                    mCallback.onActiveChanged(sessionId, active);
                     return true;
                 case MSG_SESSION_PROGRESS_CHANGED:
-                    mCallback.onProgressChanged(msg.arg1, (float) msg.obj);
-                    return true;
-                case MSG_SESSION_CLOSED:
-                    mCallback.onClosed(msg.arg1);
+                    mCallback.onProgressChanged(sessionId, (float) msg.obj);
                     return true;
                 case MSG_SESSION_FINISHED:
-                    mCallback.onFinished(msg.arg1, msg.arg2 != 0);
+                    mCallback.onFinished(sessionId, msg.arg2 != 0);
                     return true;
             }
             return false;
@@ -516,8 +549,9 @@
         }
 
         @Override
-        public void onSessionOpened(int sessionId) {
-            mHandler.obtainMessage(MSG_SESSION_OPENED, sessionId, 0).sendToTarget();
+        public void onSessionActiveChanged(int sessionId, boolean active) {
+            mHandler.obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, active ? 1 : 0)
+                    .sendToTarget();
         }
 
         @Override
@@ -527,11 +561,6 @@
         }
 
         @Override
-        public void onSessionClosed(int sessionId) {
-            mHandler.obtainMessage(MSG_SESSION_CLOSED, sessionId, 0).sendToTarget();
-        }
-
-        @Override
         public void onSessionFinished(int sessionId, boolean success) {
             mHandler.obtainMessage(MSG_SESSION_FINISHED, sessionId, success ? 1 : 0)
                     .sendToTarget();
@@ -545,7 +574,8 @@
     }
 
     /**
-     * Register to watch for session lifecycle events.
+     * Register to watch for session lifecycle events. No special permissions
+     * are required to watch for these events.
      */
     public void registerSessionCallback(@NonNull SessionCallback callback) {
         registerSessionCallback(callback, new Handler());
@@ -558,7 +588,8 @@
     }
 
     /**
-     * Register to watch for session lifecycle events.
+     * Register to watch for session lifecycle events. No special permissions
+     * are required to watch for these events.
      *
      * @param handler to dispatch callback events through, otherwise uses
      *            calling thread.
@@ -567,7 +598,7 @@
         // TODO: remove this temporary guard once we have new prebuilts
         final ApplicationInfo info = mContext.getApplicationInfo();
         if ("com.google.android.googlequicksearchbox".equals(info.packageName)
-                && info.versionCode <= 300400070) {
+                && info.versionCode <= 300400110) {
             Log.d(TAG, "Ignoring callback request from old prebuilt");
             return;
         }
@@ -591,7 +622,7 @@
     }
 
     /**
-     * Unregister an existing callback.
+     * Unregister a previously registered callback.
      */
     public void unregisterSessionCallback(@NonNull SessionCallback callback) {
         synchronized (mDelegates) {
@@ -629,10 +660,22 @@
             mSession = session;
         }
 
-        /**
-         * Set current progress. Valid values are anywhere between 0 and 1.
-         */
+        /** {@hide} */
+        @Deprecated
         public void setProgress(float progress) {
+            setStagingProgress(progress);
+        }
+
+        /**
+         * Set current progress of staging this session. Valid values are
+         * anywhere between 0 and 1.
+         * <p>
+         * Note that this progress may not directly correspond to the value
+         * reported by {@link SessionCallback#onProgressChanged(int, float)}, as
+         * the system may carve out a portion of the overall progress to
+         * represent its own internal installation work.
+         */
+        public void setStagingProgress(float progress) {
             try {
                 mSession.setClientProgress(progress);
             } catch (RemoteException e) {
@@ -672,6 +715,12 @@
          *            start at the beginning of the file.
          * @param lengthBytes total size of the file being written, used to
          *            preallocate the underlying disk space, or -1 if unknown.
+         *            The system may clear various caches as needed to allocate
+         *            this space.
+         * @throws IOException if trouble opening the file for writing, such as
+         *             lack of disk space or unavailable media.
+         * @throws SecurityException if called after the session has been
+         *             committed or abandoned.
          */
         public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes,
                 long lengthBytes) throws IOException {
@@ -705,6 +754,9 @@
          * <p>
          * This returns all names which have been previously written through
          * {@link #openWrite(String, long, long)} as part of this session.
+         *
+         * @throws SecurityException if called after the session has been
+         *             committed or abandoned.
          */
         public @NonNull String[] getNames() throws IOException {
             try {
@@ -724,6 +776,9 @@
          * through {@link #openWrite(String, long, long)} as part of this
          * session. For example, this stream may be used to calculate a
          * {@link MessageDigest} of a written APK before committing.
+         *
+         * @throws SecurityException if called after the session has been
+         *             committed or abandoned.
          */
         public @NonNull InputStream openRead(@NonNull String name) throws IOException {
             try {
@@ -745,6 +800,9 @@
          * Once this method is called, no additional mutations may be performed
          * on the session. If the device reboots before the session has been
          * finalized, you may commit the session again.
+         *
+         * @throws SecurityException if streams opened through
+         *             {@link #openWrite(String, long, long)} are still open.
          */
         public void commit(@NonNull IntentSender statusReceiver) {
             try {
@@ -769,7 +827,9 @@
 
         /**
          * Completely abandon this session, destroying all staged data and
-         * rendering it invalid.
+         * rendering it invalid. Abandoned sessions will be reported to
+         * {@link SessionCallback} listeners as failures. This is equivalent to
+         * opening the session and calling {@link Session#abandon()}.
          */
         public void abandon() {
             try {
@@ -923,6 +983,18 @@
         }
 
         /** {@hide} */
+        public void setInstallFlagsInternal() {
+            installFlags |= PackageManager.INSTALL_INTERNAL;
+            installFlags &= ~PackageManager.INSTALL_EXTERNAL;
+        }
+
+        /** {@hide} */
+        public void setInstallFlagsExternal() {
+            installFlags |= PackageManager.INSTALL_EXTERNAL;
+            installFlags &= ~PackageManager.INSTALL_INTERNAL;
+        }
+
+        /** {@hide} */
         public void dump(IndentingPrintWriter pw) {
             pw.printPair("mode", mode);
             pw.printHexPair("installFlags", installFlags);
@@ -986,7 +1058,7 @@
         /** {@hide} */
         public boolean sealed;
         /** {@hide} */
-        public boolean open;
+        public boolean active;
 
         /** {@hide} */
         public int mode;
@@ -1010,7 +1082,7 @@
             resolvedBaseCodePath = source.readString();
             progress = source.readFloat();
             sealed = source.readInt() != 0;
-            open = source.readInt() != 0;
+            active = source.readInt() != 0;
 
             mode = source.readInt();
             sizeBytes = source.readLong();
@@ -1036,20 +1108,37 @@
         /**
          * Return current overall progress of this session, between 0 and 1.
          * <p>
-         * Note that this progress may not directly correspond to the value reported
-         * by {@link PackageInstaller.Session#setProgress(float)}, as the system may
-         * carve out a portion of the overall progress to represent its own internal
-         * installation work.
+         * Note that this progress may not directly correspond to the value
+         * reported by
+         * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
+         * system may carve out a portion of the overall progress to represent
+         * its own internal installation work.
          */
         public float getProgress() {
             return progress;
         }
 
         /**
-         * Return if this session is currently open.
+         * Return if this session is currently active.
+         * <p>
+         * A session is considered active whenever there is ongoing forward
+         * progress being made, such as the installer holding an open
+         * {@link Session} instance while streaming data into place, or the
+         * system optimizing code as the result of
+         * {@link Session#commit(IntentSender)}.
+         * <p>
+         * If the installer closes the {@link Session} without committing, the
+         * session is considered inactive until the installer opens the session
+         * again.
          */
+        public boolean isActive() {
+            return active;
+        }
+
+        /** {@hide} */
+        @Deprecated
         public boolean isOpen() {
-            return open;
+            return isActive();
         }
 
         /**
@@ -1105,7 +1194,7 @@
             dest.writeString(resolvedBaseCodePath);
             dest.writeFloat(progress);
             dest.writeInt(sealed ? 1 : 0);
-            dest.writeInt(open ? 1 : 0);
+            dest.writeInt(active ? 1 : 0);
 
             dest.writeInt(mode);
             dest.writeLong(sizeBytes);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e87adda..748fca2 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -976,6 +976,14 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device includes at least one form of audio
+     * output, such as speakers, audio jack or streaming over bluetooth
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device is capable of communicating with
      * other devices via Bluetooth.
      */
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 6d40dcf..e0fd532 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3110,6 +3110,12 @@
                     false)) {
                 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
             }
+
+            if (sa.getBoolean(
+                    com.android.internal.R.styleable.AndroidManifestActivity_resumeWhilePausing,
+                    false)) {
+                a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
+            }
         } else {
             a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
             a.info.configChanges = 0;
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 2684e6c..e578822 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -773,6 +773,7 @@
     private native final String[] getArrayStringResource(int arrayRes);
     private native final int[] getArrayStringInfo(int arrayRes);
     /*package*/ native final int[] getArrayIntResource(int arrayRes);
+    /*package*/ native final int[] getStyleAttributes(int themeRes);
 
     private native final void init(boolean isSystem);
     private native final void destroy();
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 31813c10..cabe228 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1572,6 +1572,16 @@
         }
 
         /**
+         * Gets all of the attribute ids associated with this {@link Theme}. For debugging only.
+         *
+         * @return The int array containing attribute ids associated with this {@link Theme}.
+         * @hide
+         */
+        public int[] getAllAttributes() {
+            return mAssets.getStyleAttributes(getAppliedStyleResId());
+        }
+
+        /**
          * Returns the resources to which this theme belongs.
          *
          * @return Resources to which this theme belongs.
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index b52a0c5..f514e42 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -737,12 +737,11 @@
     }
 
     /**
-     * This value is defined only for continuous mode sensors. It is the delay between two
-     * sensor events corresponding to the lowest frequency that this sensor supports. When
-     * lower frequencies are requested through registerListener() the events will be generated
-     * at this frequency instead. It can be used to estimate when the batch FIFO may be full.
-     * Older devices may set this value to zero. Ignore this value in case it is negative
-     * or zero.
+     * This value is defined only for continuous and on-change sensors. It is the delay between two
+     * sensor events corresponding to the lowest frequency that this sensor supports. When lower
+     * frequencies are requested through registerListener() the events will be generated at this
+     * frequency instead. It can be used to estimate when the batch FIFO may be full. Older devices
+     * may set this value to zero. Ignore this value in case it is negative or zero.
      *
      * @return The max delay for this sensor in microseconds.
      */
diff --git a/core/java/android/hardware/camera2/CameraAccessException.java b/core/java/android/hardware/camera2/CameraAccessException.java
index ca71e81..91ef6ca 100644
--- a/core/java/android/hardware/camera2/CameraAccessException.java
+++ b/core/java/android/hardware/camera2/CameraAccessException.java
@@ -61,7 +61,7 @@
      *
      * <p>The camera has failed to open or has failed at a later time
      * as a result of some non-user interaction. Refer to
-     * {@link CameraDevice.StateListener#onError} for the exact
+     * {@link CameraDevice.StateCallback#onError} for the exact
      * nature of the error.</p>
      *
      * <p>No further calls to the camera will succeed. Clean up
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index fc2141f..29e42ea 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -32,18 +32,18 @@
  * sending images to the desired targets. Therefore the setup is done asynchronously, and
  * {@link CameraDevice#createCaptureSession createCaptureSession} will send the ready-to-use
  * CameraCaptureSession to the provided listener's
- * {@link CameraCaptureSession.StateListener#onConfigured onConfigured} callback. If configuration
+ * {@link CameraCaptureSession.StateCallback#onConfigured onConfigured} callback. If configuration
  * cannot be completed, then the
- * {@link CameraCaptureSession.StateListener#onConfigureFailed onConfigureFailed} is called, and the
+ * {@link CameraCaptureSession.StateCallback#onConfigureFailed onConfigureFailed} is called, and the
  * session will not become active.</p>
  *<!--
  * <p>Any capture requests (repeating or non-repeating) submitted before the session is ready will
  * be queued up and will begin capture once the session becomes ready. In case the session cannot be
- * configured and {@link StateListener#onConfigureFailed onConfigureFailed} is called, all queued
+ * configured and {@link StateCallback#onConfigureFailed onConfigureFailed} is called, all queued
  * capture requests are discarded.</p>
  *-->
  * <p>If a new session is created by the camera device, then the previous session is closed, and its
- * associated {@link StateListener#onClosed onClosed} callback will be invoked.  All
+ * associated {@link StateCallback#onClosed onClosed} callback will be invoked.  All
  * of the session methods will throw an IllegalStateException if called once the session is
  * closed.</p>
  *
@@ -86,7 +86,7 @@
      * looper}.
      *
      * @return int A unique capture sequence ID used by
-     *             {@link CaptureListener#onCaptureSequenceCompleted}.
+     *             {@link CaptureCallback#onCaptureSequenceCompleted}.
      *
      * @throws CameraAccessException if the camera device is no longer connected or has
      *                               encountered a fatal error
@@ -103,7 +103,7 @@
      * @see #setRepeatingBurst
      * @see #abortCaptures
      */
-    public abstract int capture(CaptureRequest request, CaptureListener listener, Handler handler)
+    public abstract int capture(CaptureRequest request, CaptureCallback listener, Handler handler)
             throws CameraAccessException;
 
     /**
@@ -131,7 +131,7 @@
      * looper}.
      *
      * @return int A unique capture sequence ID used by
-     *             {@link CaptureListener#onCaptureSequenceCompleted}.
+     *             {@link CaptureCallback#onCaptureSequenceCompleted}.
      *
      * @throws CameraAccessException if the camera device is no longer connected or has
      *                               encountered a fatal error
@@ -147,7 +147,7 @@
      * @see #setRepeatingBurst
      * @see #abortCaptures
      */
-    public abstract int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
+    public abstract int captureBurst(List<CaptureRequest> requests, CaptureCallback listener,
             Handler handler) throws CameraAccessException;
 
     /**
@@ -185,7 +185,7 @@
      * looper}.
      *
      * @return int A unique capture sequence ID used by
-     *             {@link CaptureListener#onCaptureSequenceCompleted}.
+     *             {@link CaptureCallback#onCaptureSequenceCompleted}.
      *
      * @throws CameraAccessException if the camera device is no longer connected or has
      *                               encountered a fatal error
@@ -203,7 +203,7 @@
      * @see #stopRepeating
      * @see #abortCaptures
      */
-    public abstract int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
+    public abstract int setRepeatingRequest(CaptureRequest request, CaptureCallback listener,
             Handler handler) throws CameraAccessException;
 
     /**
@@ -245,7 +245,7 @@
      * looper}.
      *
      * @return int A unique capture sequence ID used by
-     *             {@link CaptureListener#onCaptureSequenceCompleted}.
+     *             {@link CaptureCallback#onCaptureSequenceCompleted}.
      *
      * @throws CameraAccessException if the camera device is no longer connected or has
      *                               encountered a fatal error
@@ -263,7 +263,7 @@
      * @see #stopRepeating
      * @see #abortCaptures
      */
-    public abstract int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
+    public abstract int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback listener,
             Handler handler) throws CameraAccessException;
 
     /**
@@ -274,7 +274,7 @@
      *
      * <p>Any currently in-flight captures will still complete, as will any burst that is
      * mid-capture. To ensure that the device has finished processing all of its capture requests
-     * and is in ready state, wait for the {@link StateListener#onReady} callback after
+     * and is in ready state, wait for the {@link StateCallback#onReady} callback after
      * calling this method.</p>
      *
      * @throws CameraAccessException if the camera device is no longer connected or has
@@ -285,7 +285,7 @@
      *
      * @see #setRepeatingRequest
      * @see #setRepeatingBurst
-     * @see StateListener#onIdle
+     * @see StateCallback#onIdle
      */
     public abstract void stopRepeating() throws CameraAccessException;
 
@@ -293,15 +293,15 @@
      * Discard all captures currently pending and in-progress as fast as possible.
      *
      * <p>The camera device will discard all of its current work as fast as possible. Some in-flight
-     * captures may complete successfully and call {@link CaptureListener#onCaptureCompleted}, while
-     * others will trigger their {@link CaptureListener#onCaptureFailed} callbacks. If a repeating
+     * captures may complete successfully and call {@link CaptureCallback#onCaptureCompleted}, while
+     * others will trigger their {@link CaptureCallback#onCaptureFailed} callbacks. If a repeating
      * request or a repeating burst is set, it will be cleared.</p>
      *
      * <p>This method is the fastest way to switch the camera device to a new session with
      * {@link CameraDevice#createCaptureSession}, at the cost of discarding in-progress work. It
      * must be called before the new session is created. Once all pending requests are either
-     * completed or thrown away, the {@link StateListener#onReady} callback will be called,
-     * if the session has not been closed. Otherwise, the {@link StateListener#onClosed}
+     * completed or thrown away, the {@link StateCallback#onReady} callback will be called,
+     * if the session has not been closed. Otherwise, the {@link StateCallback#onClosed}
      * callback will be fired when a new session is created by the camera device.</p>
      *
      * <p>Cancelling will introduce at least a brief pause in the stream of data from the camera
@@ -332,7 +332,7 @@
      *
      * <p>Note that creating a new capture session with {@link CameraDevice#createCaptureSession}
      * will close any existing capture session automatically, and call the older session listener's
-     * {@link StateListener#onClosed} callback. Using {@link CameraDevice#createCaptureSession}
+     * {@link StateCallback#onClosed} callback. Using {@link CameraDevice#createCaptureSession}
      * directly without closing is the recommended approach for quickly switching to a new session,
      * since unchanged target outputs can be reused more efficiently.</p>
      *
@@ -340,7 +340,7 @@
      * repeating requests or bursts are stopped (as if {@link #stopRepeating()} was called).
      * However, any in-progress capture requests submitted to the session will be completed as
      * normal; once all captures have completed and the session has been torn down,
-     * {@link StateListener#onClosed} will be called.</p>
+     * {@link StateCallback#onClosed} will be called.</p>
      *
      * <p>Closing a session is idempotent; closing more than once has no effect.</p>
      */
@@ -348,10 +348,10 @@
     public abstract void close();
 
     /**
-     * A listener for tracking the state of a camera capture session.
+     * A callback object for receiving updates about the state of a camera capture session.
      *
      */
-    public static abstract class StateListener {
+    public static abstract class StateCallback {
 
         /**
          * This method is called when the camera device has finished configuring itself, and the
@@ -439,10 +439,17 @@
     }
 
     /**
-     * <p>A listener for tracking the progress of a {@link CaptureRequest}
-     * submitted to the camera device.</p>
+     * Temporary for migrating to Callback naming
+     * @hide
+     */
+    public static abstract class StateListener extends StateCallback {
+    }
+
+    /**
+     * <p>A callback object for tracking the progress of a {@link CaptureRequest} submitted to the
+     * camera device.</p>
      *
-     * <p>This listener is called when a request triggers a capture to start,
+     * <p>This callback is invoked when a request triggers a capture to start,
      * and when the capture is complete. In case on an error capturing an image,
      * the error method is triggered instead of the completion method.</p>
      *
@@ -451,7 +458,7 @@
      * @see #setRepeatingRequest
      * @see #setRepeatingBurst
      */
-    public static abstract class CaptureListener {
+    public static abstract class CaptureCallback {
 
         /**
          * This constant is used to indicate that no images were captured for
@@ -625,7 +632,7 @@
         }
 
         /**
-         * This method is called independently of the others in CaptureListener,
+         * This method is called independently of the others in CaptureCallback,
          * when a capture sequence finishes and all {@link CaptureResult}
          * or {@link CaptureFailure} for it have been returned via this listener.
          *
@@ -655,7 +662,7 @@
         }
 
         /**
-         * This method is called independently of the others in CaptureListener,
+         * This method is called independently of the others in CaptureCallback,
          * when a capture sequence aborts before any {@link CaptureResult}
          * or {@link CaptureFailure} for it have been returned via this listener.
          *
@@ -684,4 +691,11 @@
         }
     }
 
+    /**
+     * Temporary for migrating to Callback naming
+     * @hide
+     */
+    public static abstract class CaptureListener extends CaptureCallback {
+    }
+
 }
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 097b430..0bb742c 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -199,8 +199,8 @@
      * <p>It can take several hundred milliseconds for the session's configuration to complete,
      * since camera hardware may need to be powered on or reconfigured. Once the configuration is
      * complete and the session is ready to actually capture data, the provided
-     * {@link CameraCaptureSession.StateListener}'s
-     * {@link CameraCaptureSession.StateListener#onConfigured} callback will be called.</p>
+     * {@link CameraCaptureSession.StateCallback}'s
+     * {@link CameraCaptureSession.StateCallback#onConfigured} callback will be called.</p>
      *
      * <p>If a prior CameraCaptureSession already exists when a new one is created, the previous
      * session is closed. Any in-progress capture requests made on the prior session will be
@@ -340,12 +340,12 @@
      *
      * @param outputs The new set of Surfaces that should be made available as
      *                targets for captured image data.
-     * @param listener The listener to notify about the status of the new capture session.
-     * @param handler The handler on which the listener should be invoked, or {@code null} to use
+     * @param callback The callback to notify about the status of the new capture session.
+     * @param handler The handler on which the callback should be invoked, or {@code null} to use
      *                the current thread's {@link android.os.Looper looper}.
      *
      * @throws IllegalArgumentException if the set of output Surfaces do not meet the requirements,
-     *                                  the listener is null, or the handler is null but the current
+     *                                  the callback is null, or the handler is null but the current
      *                                  thread has no looper.
      * @throws CameraAccessException if the camera device is no longer connected or has
      *                               encountered a fatal error
@@ -357,7 +357,7 @@
      * @see StreamConfigurationMap#getOutputSizes(Class)
      */
     public abstract void createCaptureSession(List<Surface> outputs,
-            CameraCaptureSession.StateListener listener, Handler handler)
+            CameraCaptureSession.StateCallback callback, Handler handler)
             throws CameraAccessException;
 
     /**
@@ -393,10 +393,10 @@
      *
      * <p>Immediately after this call, all calls to the camera device or active session interface
      * will throw a {@link IllegalStateException}, except for calls to close(). Once the device has
-     * fully shut down, the {@link StateListener#onClosed} callback will be called, and the camera
+     * fully shut down, the {@link StateCallback#onClosed} callback will be called, and the camera
      * is free to be re-opened.</p>
      *
-     * <p>Immediately after this call, besides the final {@link StateListener#onClosed} calls, no
+     * <p>Immediately after this call, besides the final {@link StateCallback#onClosed} calls, no
      * further callbacks from the device or the active session will occur, and any remaining
      * submitted capture requests will be discarded, as if
      * {@link CameraCaptureSession#abortCaptures} had been called, except that no success or failure
@@ -407,24 +407,24 @@
     public abstract void close();
 
     /**
-     * A listener for notifications about the state of a camera
-     * device.
+     * A callback objects for receiving updates about the state of a camera device.
      *
-     * <p>A listener must be provided to the {@link CameraManager#openCamera}
-     * method to open a camera device.</p>
+     * <p>A callback instance must be provided to the {@link CameraManager#openCamera} method to
+     * open a camera device.</p>
      *
-     * <p>These events include notifications about the device completing startup (
+     * <p>These state updates include notifications about the device completing startup (
      * allowing for {@link #createCaptureSession} to be called), about device
      * disconnection or closure, and about unexpected device errors.</p>
      *
      * <p>Events about the progress of specific {@link CaptureRequest CaptureRequests} are provided
-     * through a {@link CameraCaptureSession.CaptureListener} given to the
+     * through a {@link CameraCaptureSession.CaptureCallback} given to the
      * {@link CameraCaptureSession#capture}, {@link CameraCaptureSession#captureBurst},
-     * {@link CameraCaptureSession#setRepeatingRequest}, or {@link CameraCaptureSession#setRepeatingBurst} methods.
+     * {@link CameraCaptureSession#setRepeatingRequest}, or
+     * {@link CameraCaptureSession#setRepeatingBurst} methods.
      *
      * @see CameraManager#openCamera
      */
-    public static abstract class StateListener {
+    public static abstract class StateCallback {
        /**
          * An error code that can be reported by {@link #onError}
          * indicating that the camera device is in use already.
@@ -530,7 +530,7 @@
          * of a removable camera device; or the camera being needed for a
          * higher-priority use case.</p>
          *
-         * <p>There may still be capture listener callbacks that are called
+         * <p>There may still be capture callbacks that are invoked
          * after this method is called, or new image buffers that are delivered
          * to active outputs.</p>
          *
@@ -539,7 +539,7 @@
          *
          * <p>You should clean up the camera with {@link CameraDevice#close} after
          * this happens, as it is not recoverable until opening the camera again
-         * after it becomes {@link CameraManager.AvailabilityListener#onCameraAvailable available}.
+         * after it becomes {@link CameraManager.AvailabilityCallback#onCameraAvailable available}.
          * </p>
          *
          * @param camera the device that has been disconnected
@@ -558,7 +558,7 @@
          * {@link CameraAccessException#CAMERA_ERROR CAMERA_ERROR} reason.
          * </p>
          *
-         * <p>There may still be capture completion or camera stream listeners
+         * <p>There may still be capture completion or camera stream callbacks
          * that will be called after this error is received.</p>
          *
          * <p>You should clean up the camera with {@link CameraDevice#close} after
@@ -566,7 +566,7 @@
          *
          * @param camera The device reporting the error
          * @param error The error code, one of the
-         *     {@code StateListener.ERROR_*} values.
+         *     {@code StateCallback.ERROR_*} values.
          *
          * @see #ERROR_CAMERA_DEVICE
          * @see #ERROR_CAMERA_SERVICE
@@ -577,6 +577,13 @@
     }
 
     /**
+     * Temporary for migrating to Callback naming
+     * @hide
+     */
+    public static abstract class StateListener extends StateCallback {
+    }
+
+    /**
      * To be inherited by android.hardware.camera2.* code only.
      * @hide
      */
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index a4a1559..9a9e4c2 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -69,8 +69,8 @@
 
     private ArrayList<String> mDeviceIdList;
 
-    private final ArrayMap<AvailabilityListener, Handler> mListenerMap =
-            new ArrayMap<AvailabilityListener, Handler>();
+    private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap =
+            new ArrayMap<AvailabilityCallback, Handler>();
 
     private final Context mContext;
     private final Object mLock = new Object();
@@ -108,19 +108,19 @@
     }
 
     /**
-     * Register a listener to be notified about camera device availability.
+     * Register a callback to be notified about camera device availability.
      *
-     * <p>Registering the same listener again will replace the handler with the
+     * <p>Registering the same callback again will replace the handler with the
      * new one provided.</p>
      *
-     * <p>The first time a listener is registered, it is immediately called
+     * <p>The first time a callback is registered, it is immediately called
      * with the availability status of all currently known camera devices.</p>
      *
-     * @param listener The new listener to send camera availability notices to
-     * @param handler The handler on which the listener should be invoked, or
+     * @param callback the new callback to send camera availability notices to
+     * @param handler The handler on which the callback should be invoked, or
      * {@code null} to use the current thread's {@link android.os.Looper looper}.
      */
-    public void addAvailabilityListener(AvailabilityListener listener, Handler handler) {
+    public void registerAvailabilityCallback(AvailabilityCallback callback, Handler handler) {
         if (handler == null) {
             Looper looper = Looper.myLooper();
             if (looper == null) {
@@ -131,25 +131,25 @@
         }
 
         synchronized (mLock) {
-            Handler oldHandler = mListenerMap.put(listener, handler);
-            // For new listeners, provide initial availability information
+            Handler oldHandler = mCallbackMap.put(callback, handler);
+            // For new callbacks, provide initial availability information
             if (oldHandler == null) {
-                mServiceListener.updateListenerLocked(listener, handler);
+                mServiceListener.updateCallbackLocked(callback, handler);
             }
         }
     }
 
     /**
-     * Remove a previously-added listener; the listener will no longer receive
-     * connection and disconnection callbacks.
+     * Remove a previously-added callback; the callback will no longer receive connection and
+     * disconnection callbacks.
      *
-     * <p>Removing a listener that isn't registered has no effect.</p>
+     * <p>Removing a callback that isn't registered has no effect.</p>
      *
-     * @param listener The listener to remove from the notification list
+     * @param callback The callback to remove from the notification list
      */
-    public void removeAvailabilityListener(AvailabilityListener listener) {
+    public void unregisterAvailabilityCallback(AvailabilityCallback callback) {
         synchronized (mLock) {
-            mListenerMap.remove(listener);
+            mCallbackMap.remove(callback);
         }
     }
 
@@ -228,8 +228,8 @@
      * Helper for openning a connection to a camera with the given ID.
      *
      * @param cameraId The unique identifier of the camera device to open
-     * @param listener The listener for the camera. Must not be null.
-     * @param handler  The handler to call the listener on. Must not be null.
+     * @param callback The callback for the camera. Must not be null.
+     * @param handler  The handler to invoke the callback on. Must not be null.
      *
      * @throws CameraAccessException if the camera is disabled by device policy,
      * or too many camera devices are already open, or the cameraId does not match
@@ -237,14 +237,14 @@
      *
      * @throws SecurityException if the application does not have permission to
      * access the camera
-     * @throws IllegalArgumentException if listener or handler is null.
+     * @throws IllegalArgumentException if callback or handler is null.
      * @return A handle to the newly-created camera device.
      *
      * @see #getCameraIdList
      * @see android.app.admin.DevicePolicyManager#setCameraDisabled
      */
     private CameraDevice openCameraDeviceUserAsync(String cameraId,
-            CameraDevice.StateListener listener, Handler handler)
+            CameraDevice.StateCallback callback, Handler handler)
             throws CameraAccessException {
         CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
         CameraDevice device = null;
@@ -257,7 +257,7 @@
                 android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
                         new android.hardware.camera2.impl.CameraDeviceImpl(
                                 cameraId,
-                                listener,
+                                callback,
                                 handler,
                                 characteristics);
 
@@ -313,7 +313,7 @@
                     throw ce.asChecked();
                 }
 
-                // TODO: factor out listener to be non-nested, then move setter to constructor
+                // TODO: factor out callback to be non-nested, then move setter to constructor
                 // For now, calling setRemoteDevice will fire initial
                 // onOpened/onUnconfigured callbacks.
                 deviceImpl.setRemoteDevice(cameraUser);
@@ -337,7 +337,7 @@
      * is disconnected between the calls to {@link #getCameraIdList} and
      * {@link #openCamera}.</p>
      *
-     * <p>Once the camera is successfully opened, {@link CameraDevice.StateListener#onOpened} will
+     * <p>Once the camera is successfully opened, {@link CameraDevice.StateCallback#onOpened} will
      * be invoked with the newly opened {@link CameraDevice}. The camera device can then be set up
      * for operation by calling {@link CameraDevice#createCaptureSession} and
      * {@link CameraDevice#createCaptureRequest}</p>
@@ -345,31 +345,31 @@
      * <!--
      * <p>Since the camera device will be opened asynchronously, any asynchronous operations done
      * on the returned CameraDevice instance will be queued up until the device startup has
-     * completed and the listener's {@link CameraDevice.StateListener#onOpened onOpened} method is
+     * completed and the callback's {@link CameraDevice.StateCallback#onOpened onOpened} method is
      * called. The pending operations are then processed in order.</p>
      * -->
      * <p>If the camera becomes disconnected during initialization
      * after this function call returns,
-     * {@link CameraDevice.StateListener#onDisconnected} with a
+     * {@link CameraDevice.StateCallback#onDisconnected} with a
      * {@link CameraDevice} in the disconnected state (and
-     * {@link CameraDevice.StateListener#onOpened} will be skipped).</p>
+     * {@link CameraDevice.StateCallback#onOpened} will be skipped).</p>
      *
-     * <p>If opening the camera device fails, then the device listener's
-     * {@link CameraDevice.StateListener#onError onError} method will be called, and subsequent
+     * <p>If opening the camera device fails, then the device callback's
+     * {@link CameraDevice.StateCallback#onError onError} method will be called, and subsequent
      * calls on the camera device will throw a {@link CameraAccessException}.</p>
      *
      * @param cameraId
      *             The unique identifier of the camera device to open
-     * @param listener
-     *             The listener which is invoked once the camera is opened
+     * @param callback
+     *             The callback which is invoked once the camera is opened
      * @param handler
-     *             The handler on which the listener should be invoked, or
+     *             The handler on which the callback should be invoked, or
      *             {@code null} to use the current thread's {@link android.os.Looper looper}.
      *
      * @throws CameraAccessException if the camera is disabled by device policy,
      * or the camera has become or was disconnected.
      *
-     * @throws IllegalArgumentException if cameraId or the listener was null,
+     * @throws IllegalArgumentException if cameraId or the callback was null,
      * or the cameraId does not match any currently or previously available
      * camera device.
      *
@@ -379,14 +379,14 @@
      * @see #getCameraIdList
      * @see android.app.admin.DevicePolicyManager#setCameraDisabled
      */
-    public void openCamera(String cameraId, final CameraDevice.StateListener listener,
+    public void openCamera(String cameraId, final CameraDevice.StateCallback callback,
             Handler handler)
             throws CameraAccessException {
 
         if (cameraId == null) {
             throw new IllegalArgumentException("cameraId was null");
-        } else if (listener == null) {
-            throw new IllegalArgumentException("listener was null");
+        } else if (callback == null) {
+            throw new IllegalArgumentException("callback was null");
         } else if (handler == null) {
             if (Looper.myLooper() != null) {
                 handler = new Handler();
@@ -396,11 +396,11 @@
             }
         }
 
-        openCameraDeviceUserAsync(cameraId, listener, handler);
+        openCameraDeviceUserAsync(cameraId, callback, handler);
     }
 
     /**
-     * A listener for camera devices becoming available or
+     * A callback for camera devices becoming available or
      * unavailable to open.
      *
      * <p>Cameras become available when they are no longer in use, or when a new
@@ -408,13 +408,13 @@
      * application or service starts using a camera, or when a removable camera
      * is disconnected.</p>
      *
-     * <p>Extend this listener and pass an instance of the subclass to
-     * {@link CameraManager#addAvailabilityListener} to be notified of such availability
+     * <p>Extend this callback and pass an instance of the subclass to
+     * {@link CameraManager#registerAvailabilityCallback} to be notified of such availability
      * changes.</p>
      *
-     * @see addAvailabilityListener
+     * @see registerAvailabilityCallback
      */
-    public static abstract class AvailabilityListener {
+    public static abstract class AvailabilityCallback {
 
         /**
          * A new camera has become available to use.
@@ -432,7 +432,7 @@
          *
          * <p>If an application had an active CameraDevice instance for the
          * now-disconnected camera, that application will receive a
-         * {@link CameraDevice.StateListener#onDisconnected disconnection error}.</p>
+         * {@link CameraDevice.StateCallback#onDisconnected disconnection error}.</p>
          *
          * <p>The default implementation of this method does nothing.</p>
          *
@@ -444,6 +444,13 @@
     }
 
     /**
+     * Temporary for migrating to Callback naming
+     * @hide
+     */
+    public static abstract class AvailabilityListener extends AvailabilityCallback {
+    }
+
+    /**
      * Return or create the list of currently connected camera devices.
      *
      * <p>In case of errors connecting to the camera service, will return an empty list.</p>
@@ -707,14 +714,14 @@
             }
         }
 
-        private void postSingleUpdate(final AvailabilityListener listener, final Handler handler,
+        private void postSingleUpdate(final AvailabilityCallback callback, final Handler handler,
                 final String id, final int status) {
             if (isAvailable(status)) {
                 handler.post(
                     new Runnable() {
                         @Override
                         public void run() {
-                            listener.onCameraAvailable(id);
+                            callback.onCameraAvailable(id);
                         }
                     });
             } else {
@@ -722,7 +729,7 @@
                     new Runnable() {
                         @Override
                         public void run() {
-                            listener.onCameraUnavailable(id);
+                            callback.onCameraUnavailable(id);
                         }
                     });
             }
@@ -732,11 +739,11 @@
          * Send the state of all known cameras to the provided listener, to initialize
          * the listener's knowledge of camera state.
          */
-        public void updateListenerLocked(AvailabilityListener listener, Handler handler) {
+        public void updateCallbackLocked(AvailabilityCallback callback, Handler handler) {
             for (int i = 0; i < mDeviceStatus.size(); i++) {
                 String id = mDeviceStatus.keyAt(i);
                 Integer status = mDeviceStatus.valueAt(i);
-                postSingleUpdate(listener, handler, id, status);
+                postSingleUpdate(callback, handler, id, status);
             }
         }
 
@@ -795,12 +802,12 @@
                 return;
             }
 
-            final int listenerCount = mListenerMap.size();
-            for (int i = 0; i < listenerCount; i++) {
-                Handler handler = mListenerMap.valueAt(i);
-                final AvailabilityListener listener = mListenerMap.keyAt(i);
+            final int callbackCount = mCallbackMap.size();
+            for (int i = 0; i < callbackCount; i++) {
+                Handler handler = mCallbackMap.valueAt(i);
+                final AvailabilityCallback callback = mCallbackMap.keyAt(i);
 
-                postSingleUpdate(listener, handler, id, status);
+                postSingleUpdate(callback, handler, id, status);
             }
         } // onStatusChangedLocked
 
diff --git a/core/java/android/hardware/camera2/CaptureFailure.java b/core/java/android/hardware/camera2/CaptureFailure.java
index b6d3b08..c168ff1 100644
--- a/core/java/android/hardware/camera2/CaptureFailure.java
+++ b/core/java/android/hardware/camera2/CaptureFailure.java
@@ -65,12 +65,12 @@
      * Get the request associated with this failed capture.
      *
      * <p>Whenever a request is unsuccessfully captured, with
-     * {@link CameraCaptureSession.CaptureListener#onCaptureFailed},
+     * {@link CameraCaptureSession.CaptureCallback#onCaptureFailed},
      * the {@code failed capture}'s {@code getRequest()} will return that {@code request}.
      * </p>
      *
      * <p>In particular,
-     * <code><pre>cameraDevice.capture(someRequest, new CaptureListener() {
+     * <code><pre>cameraDevice.capture(someRequest, new CaptureCallback() {
      *     {@literal @}Override
      *     void onCaptureFailed(CaptureRequest myRequest, CaptureFailure myFailure) {
      *         assert(myFailure.getRequest.equals(myRequest) == true);
@@ -135,7 +135,7 @@
      *
      * @return int The ID for the sequence of requests that this capture failure is the result of
      *
-     * @see CameraDevice.CaptureListener#onCaptureSequenceCompleted
+     * @see CameraDevice.CaptureCallback#onCaptureSequenceCompleted
      */
     public int getSequenceId() {
         return mSequenceId;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index bcdcd62..6d0d505 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -245,7 +245,7 @@
      * <p>This tag is not used for anything by the camera device, but can be
      * used by an application to easily identify a CaptureRequest when it is
      * returned by
-     * {@link CameraCaptureSession.CaptureListener#onCaptureCompleted CaptureListener.onCaptureCompleted}
+     * {@link CameraCaptureSession.CaptureCallback#onCaptureCompleted CaptureCallback.onCaptureCompleted}
      * </p>
      *
      * @return the last tag Object set on this request, or {@code null} if
@@ -435,7 +435,7 @@
          * <p>This tag is not used for anything by the camera device, but can be
          * used by an application to easily identify a CaptureRequest when it is
          * returned by
-         * {@link CameraCaptureSession.CaptureListener#onCaptureCompleted CaptureListener.onCaptureCompleted}
+         * {@link CameraCaptureSession.CaptureCallback#onCaptureCompleted CaptureCallback.onCaptureCompleted}
          *
          * @param tag an arbitrary Object to store with this request
          * @see CaptureRequest#getTag
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index f9c4df4..754d83e 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -268,13 +268,13 @@
      * Get the request associated with this result.
      *
      * <p>Whenever a request has been fully or partially captured, with
-     * {@link CameraCaptureSession.CaptureListener#onCaptureCompleted} or
-     * {@link CameraCaptureSession.CaptureListener#onCaptureProgressed}, the {@code result}'s
+     * {@link CameraCaptureSession.CaptureCallback#onCaptureCompleted} or
+     * {@link CameraCaptureSession.CaptureCallback#onCaptureProgressed}, the {@code result}'s
      * {@code getRequest()} will return that {@code request}.
      * </p>
      *
      * <p>For example,
-     * <code><pre>cameraDevice.capture(someRequest, new CaptureListener() {
+     * <code><pre>cameraDevice.capture(someRequest, new CaptureCallback() {
      *     {@literal @}Override
      *     void onCaptureCompleted(CaptureRequest myRequest, CaptureResult myResult) {
      *         assert(myResult.getRequest.equals(myRequest) == true);
@@ -314,8 +314,8 @@
      *
      * @return int The ID for the sequence of requests that this capture result is a part of
      *
-     * @see CameraDevice.CaptureListener#onCaptureSequenceCompleted
-     * @see CameraDevice.CaptureListener#onCaptureSequenceAborted
+     * @see CameraDevice.CaptureCallback#onCaptureSequenceCompleted
+     * @see CameraDevice.CaptureCallback#onCaptureSequenceAborted
      */
     public int getSequenceId() {
         return mSequenceId;
diff --git a/core/java/android/hardware/camera2/TotalCaptureResult.java b/core/java/android/hardware/camera2/TotalCaptureResult.java
index 0895fe3..6f7dd78 100644
--- a/core/java/android/hardware/camera2/TotalCaptureResult.java
+++ b/core/java/android/hardware/camera2/TotalCaptureResult.java
@@ -45,7 +45,7 @@
  *
  * <p>{@link TotalCaptureResult} objects are immutable.</p>
  *
- * @see CameraDevice.CaptureListener#onCaptureCompleted
+ * @see CameraDevice.CaptureCallback#onCaptureCompleted
  */
 public final class TotalCaptureResult extends CaptureResult {
 
@@ -88,7 +88,7 @@
      *
      * <p>The list size will be inclusive between {@code 0} and
      * {@link CameraCharacteristics#REQUEST_PARTIAL_RESULT_COUNT}, with elements in ascending order
-     * of when {@link CameraCaptureSession.CaptureListener#onCaptureProgressed} was invoked.</p>
+     * of when {@link CameraCaptureSession.CaptureCallback#onCaptureProgressed} was invoked.</p>
      *
      * @return unmodifiable list of partial results
      */
diff --git a/core/java/android/hardware/camera2/impl/ListenerProxies.java b/core/java/android/hardware/camera2/impl/CallbackProxies.java
similarity index 84%
rename from core/java/android/hardware/camera2/impl/ListenerProxies.java
rename to core/java/android/hardware/camera2/impl/CallbackProxies.java
index f44f9ad..e5ddb7a 100644
--- a/core/java/android/hardware/camera2/impl/ListenerProxies.java
+++ b/core/java/android/hardware/camera2/impl/CallbackProxies.java
@@ -27,22 +27,22 @@
 import static com.android.internal.util.Preconditions.*;
 
 /**
- * Proxy out invocations to the camera2 API listeners into a {@link Dispatchable}.
+ * Proxy out invocations to the camera2 API callbacks into a {@link Dispatchable}.
  *
  * <p>Since abstract classes do not support Java's dynamic {@code Proxy}, we have to
  * to use our own proxy mechanism.</p>
  */
-public class ListenerProxies {
+public class CallbackProxies {
 
     // TODO: replace with codegen
 
-    public static class DeviceStateListenerProxy extends CameraDeviceImpl.StateListenerKK {
-        private final MethodNameInvoker<CameraDeviceImpl.StateListenerKK> mProxy;
+    public static class DeviceStateCallbackProxy extends CameraDeviceImpl.StateCallbackKK {
+        private final MethodNameInvoker<CameraDeviceImpl.StateCallbackKK> mProxy;
 
-        public DeviceStateListenerProxy(
-                Dispatchable<CameraDeviceImpl.StateListenerKK> dispatchTarget) {
+        public DeviceStateCallbackProxy(
+                Dispatchable<CameraDeviceImpl.StateCallbackKK> dispatchTarget) {
             dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
-            mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.StateListenerKK.class);
+            mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.StateCallbackKK.class);
         }
 
         @Override
@@ -87,13 +87,13 @@
     }
 
     @SuppressWarnings("deprecation")
-    public static class DeviceCaptureListenerProxy extends CameraDeviceImpl.CaptureListener {
-        private final MethodNameInvoker<CameraDeviceImpl.CaptureListener> mProxy;
+    public static class DeviceCaptureCallbackProxy extends CameraDeviceImpl.CaptureCallback {
+        private final MethodNameInvoker<CameraDeviceImpl.CaptureCallback> mProxy;
 
-        public DeviceCaptureListenerProxy(
-                Dispatchable<CameraDeviceImpl.CaptureListener> dispatchTarget) {
+        public DeviceCaptureCallbackProxy(
+                Dispatchable<CameraDeviceImpl.CaptureCallback> dispatchTarget) {
             dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
-            mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.CaptureListener.class);
+            mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.CaptureCallback.class);
         }
 
         @Override
@@ -139,15 +139,15 @@
         }
     }
 
-    public static class SessionStateListenerProxy
-            extends CameraCaptureSession.StateListener {
-        private final MethodNameInvoker<CameraCaptureSession.StateListener> mProxy;
+    public static class SessionStateCallbackProxy
+            extends CameraCaptureSession.StateCallback {
+        private final MethodNameInvoker<CameraCaptureSession.StateCallback> mProxy;
 
-        public SessionStateListenerProxy(
-                Dispatchable<CameraCaptureSession.StateListener> dispatchTarget) {
+        public SessionStateCallbackProxy(
+                Dispatchable<CameraCaptureSession.StateCallback> dispatchTarget) {
             dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
             mProxy = new MethodNameInvoker<>(dispatchTarget,
-                    CameraCaptureSession.StateListener.class);
+                    CameraCaptureSession.StateCallback.class);
         }
 
         @Override
@@ -177,7 +177,7 @@
         }
     }
 
-    private ListenerProxies() {
+    private CallbackProxies() {
         throw new AssertionError();
     }
 }
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 9ca1fba..843f117 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -45,11 +45,11 @@
     /** User-specified set of surfaces used as the configuration outputs */
     private final List<Surface> mOutputs;
     /**
-     * User-specified state listener, used for outgoing events; calls to this object will be
+     * User-specified state callback, used for outgoing events; calls to this object will be
      * automatically {@link Handler#post(Runnable) posted} to {@code mStateHandler}.
      */
-    private final CameraCaptureSession.StateListener mStateListener;
-    /** User-specified state handler used for outgoing state listener events */
+    private final CameraCaptureSession.StateCallback mStateCallback;
+    /** User-specified state handler used for outgoing state callback events */
     private final Handler mStateHandler;
 
     /** Internal camera device; used to translate calls into existing deprecated API */
@@ -84,28 +84,28 @@
      * (e.g. no pending captures, no repeating requests, no flush).</p>
      */
     CameraCaptureSessionImpl(List<Surface> outputs,
-            CameraCaptureSession.StateListener listener, Handler stateHandler,
+            CameraCaptureSession.StateCallback callback, Handler stateHandler,
             android.hardware.camera2.impl.CameraDeviceImpl deviceImpl,
             Handler deviceStateHandler, boolean configureSuccess) {
         if (outputs == null || outputs.isEmpty()) {
             throw new IllegalArgumentException("outputs must be a non-null, non-empty list");
-        } else if (listener == null) {
-            throw new IllegalArgumentException("listener must not be null");
+        } else if (callback == null) {
+            throw new IllegalArgumentException("callback must not be null");
         }
 
         // TODO: extra verification of outputs
         mOutputs = outputs;
         mStateHandler = checkHandler(stateHandler);
-        mStateListener = createUserStateListenerProxy(mStateHandler, listener);
+        mStateCallback = createUserStateCallbackProxy(mStateHandler, callback);
 
         mDeviceHandler = checkNotNull(deviceStateHandler, "deviceStateHandler must not be null");
         mDeviceImpl = checkNotNull(deviceImpl, "deviceImpl must not be null");
 
         /*
-         * Use the same handler as the device's StateListener for all the internal coming events
+         * Use the same handler as the device's StateCallback for all the internal coming events
          *
-         * This ensures total ordering between CameraDevice.StateListener and
-         * CameraDeviceImpl.CaptureListener events.
+         * This ensures total ordering between CameraDevice.StateCallback and
+         * CameraDeviceImpl.CaptureCallback events.
          */
         mSequenceDrainer = new TaskDrainer<>(mDeviceHandler, new SequenceDrainListener(),
                 /*name*/"seq");
@@ -119,11 +119,11 @@
         // CameraDevice should call configureOutputs and have it finish before constructing us
 
         if (configureSuccess) {
-            mStateListener.onConfigured(this);
+            mStateCallback.onConfigured(this);
             if (VERBOSE) Log.v(TAG, "ctor - Created session successfully");
             mConfigureSuccess = true;
         } else {
-            mStateListener.onConfigureFailed(this);
+            mStateCallback.onConfigureFailed(this);
             mClosed = true; // do not fire any other callbacks, do not allow any other work
             Log.e(TAG, "Failed to create capture session; configuration failed");
             mConfigureSuccess = false;
@@ -136,7 +136,7 @@
     }
 
     @Override
-    public synchronized int capture(CaptureRequest request, CaptureListener listener,
+    public synchronized int capture(CaptureRequest request, CaptureCallback callback,
             Handler handler) throws CameraAccessException {
         if (request == null) {
             throw new IllegalArgumentException("request must not be null");
@@ -145,19 +145,19 @@
         checkNotClosed();
         checkLegalToCapture();
 
-        handler = checkHandler(handler, listener);
+        handler = checkHandler(handler, callback);
 
         if (VERBOSE) {
-            Log.v(TAG, "capture - request " + request + ", listener " + listener + " handler" +
+            Log.v(TAG, "capture - request " + request + ", callback " + callback + " handler" +
                     " " + handler);
         }
 
         return addPendingSequence(mDeviceImpl.capture(request,
-                createCaptureListenerProxy(handler, listener), mDeviceHandler));
+                createCaptureCallbackProxy(handler, callback), mDeviceHandler));
     }
 
     @Override
-    public synchronized int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
+    public synchronized int captureBurst(List<CaptureRequest> requests, CaptureCallback callback,
             Handler handler) throws CameraAccessException {
         if (requests == null) {
             throw new IllegalArgumentException("requests must not be null");
@@ -168,20 +168,20 @@
         checkNotClosed();
         checkLegalToCapture();
 
-        handler = checkHandler(handler, listener);
+        handler = checkHandler(handler, callback);
 
         if (VERBOSE) {
             CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
-            Log.v(TAG, "captureBurst - requests " + Arrays.toString(requestArray) + ", listener " +
-                    listener + " handler" + "" + handler);
+            Log.v(TAG, "captureBurst - requests " + Arrays.toString(requestArray) + ", callback " +
+                    callback + " handler" + "" + handler);
         }
 
         return addPendingSequence(mDeviceImpl.captureBurst(requests,
-                createCaptureListenerProxy(handler, listener), mDeviceHandler));
+                createCaptureCallbackProxy(handler, callback), mDeviceHandler));
     }
 
     @Override
-    public synchronized int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
+    public synchronized int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
             Handler handler) throws CameraAccessException {
         if (request == null) {
             throw new IllegalArgumentException("request must not be null");
@@ -190,20 +190,20 @@
         checkNotClosed();
         checkLegalToCapture();
 
-        handler = checkHandler(handler, listener);
+        handler = checkHandler(handler, callback);
 
         if (VERBOSE) {
-            Log.v(TAG, "setRepeatingRequest - request " + request + ", listener " + listener +
+            Log.v(TAG, "setRepeatingRequest - request " + request + ", callback " + callback +
                     " handler" + " " + handler);
         }
 
         return addPendingSequence(mDeviceImpl.setRepeatingRequest(request,
-                createCaptureListenerProxy(handler, listener), mDeviceHandler));
+                createCaptureCallbackProxy(handler, callback), mDeviceHandler));
     }
 
     @Override
     public synchronized int setRepeatingBurst(List<CaptureRequest> requests,
-            CaptureListener listener, Handler handler) throws CameraAccessException {
+            CaptureCallback callback, Handler handler) throws CameraAccessException {
         if (requests == null) {
             throw new IllegalArgumentException("requests must not be null");
         } else if (requests.isEmpty()) {
@@ -213,16 +213,16 @@
         checkNotClosed();
         checkLegalToCapture();
 
-        handler = checkHandler(handler, listener);
+        handler = checkHandler(handler, callback);
 
         if (VERBOSE) {
             CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
             Log.v(TAG, "setRepeatingBurst - requests " + Arrays.toString(requestArray) +
-                    ", listener " + listener + " handler" + "" + handler);
+                    ", callback " + callback + " handler" + "" + handler);
         }
 
         return addPendingSequence(mDeviceImpl.setRepeatingBurst(requests,
-                createCaptureListenerProxy(handler, listener), mDeviceHandler));
+                createCaptureCallbackProxy(handler, callback), mDeviceHandler));
     }
 
     @Override
@@ -331,8 +331,8 @@
             // or just suppress the ISE only and rely onClosed.
             // Also skip any of the draining work if this is already closed.
 
-            // Short-circuit; queue listener immediately and return
-            mStateListener.onClosed(this);
+            // Short-circuit; queue callback immediately and return
+            mStateCallback.onClosed(this);
             return;
         } catch (CameraAccessException e) {
             // OK: close does not throw checked exceptions.
@@ -360,30 +360,30 @@
     }
 
     /**
-     * Post calls into a CameraCaptureSession.StateListener to the user-specified {@code handler}.
+     * Post calls into a CameraCaptureSession.StateCallback to the user-specified {@code handler}.
      */
-    private StateListener createUserStateListenerProxy(Handler handler, StateListener listener) {
-        InvokeDispatcher<StateListener> userListenerSink = new InvokeDispatcher<>(listener);
-        HandlerDispatcher<StateListener> handlerPassthrough =
-                new HandlerDispatcher<>(userListenerSink, handler);
+    private StateCallback createUserStateCallbackProxy(Handler handler, StateCallback callback) {
+        InvokeDispatcher<StateCallback> userCallbackSink = new InvokeDispatcher<>(callback);
+        HandlerDispatcher<StateCallback> handlerPassthrough =
+                new HandlerDispatcher<>(userCallbackSink, handler);
 
-        return new ListenerProxies.SessionStateListenerProxy(handlerPassthrough);
+        return new CallbackProxies.SessionStateCallbackProxy(handlerPassthrough);
     }
 
     /**
      * Forward callbacks from
-     * CameraDeviceImpl.CaptureListener to the CameraCaptureSession.CaptureListener.
+     * CameraDeviceImpl.CaptureCallback to the CameraCaptureSession.CaptureCallback.
      *
      * <p>In particular, all calls are automatically split to go both to our own
-     * internal listener, and to the user-specified listener (by transparently posting
+     * internal callback, and to the user-specified callback (by transparently posting
      * to the user-specified handler).</p>
      *
      * <p>When a capture sequence finishes, update the pending checked sequences set.</p>
      */
     @SuppressWarnings("deprecation")
-    private CameraDeviceImpl.CaptureListener createCaptureListenerProxy(
-            Handler handler, CaptureListener listener) {
-        CameraDeviceImpl.CaptureListener localListener = new CameraDeviceImpl.CaptureListener() {
+    private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxy(
+            Handler handler, CaptureCallback callback) {
+        CameraDeviceImpl.CaptureCallback localCallback = new CameraDeviceImpl.CaptureCallback() {
             @Override
             public void onCaptureSequenceCompleted(CameraDevice camera,
                     int sequenceId, long frameNumber) {
@@ -398,43 +398,43 @@
         };
 
         /*
-         * Split the calls from the device listener into local listener and the following chain:
+         * Split the calls from the device callback into local callback and the following chain:
          * - replace the first CameraDevice arg with a CameraCaptureSession
-         * - duck type from device listener to session listener
+         * - duck type from device callback to session callback
          * - then forward the call to a handler
-         * - then finally invoke the destination method on the session listener object
+         * - then finally invoke the destination method on the session callback object
          */
-        if (listener == null) {
-            // OK: API allows the user to not specify a listener, and the handler may
+        if (callback == null) {
+            // OK: API allows the user to not specify a callback, and the handler may
             // also be null in that case. Collapse whole dispatch chain to only call the local
-            // listener
-            return localListener;
+            // callback
+            return localCallback;
         }
 
-        InvokeDispatcher<CameraDeviceImpl.CaptureListener> localSink =
-                new InvokeDispatcher<>(localListener);
+        InvokeDispatcher<CameraDeviceImpl.CaptureCallback> localSink =
+                new InvokeDispatcher<>(localCallback);
 
-        InvokeDispatcher<CaptureListener> userListenerSink =
-                new InvokeDispatcher<>(listener);
-        HandlerDispatcher<CaptureListener> handlerPassthrough =
-                new HandlerDispatcher<>(userListenerSink, handler);
-        DuckTypingDispatcher<CameraDeviceImpl.CaptureListener, CaptureListener> duckToSession
-                = new DuckTypingDispatcher<>(handlerPassthrough, CaptureListener.class);
-        ArgumentReplacingDispatcher<CameraDeviceImpl.CaptureListener, CameraCaptureSessionImpl>
+        InvokeDispatcher<CaptureCallback> userCallbackSink =
+                new InvokeDispatcher<>(callback);
+        HandlerDispatcher<CaptureCallback> handlerPassthrough =
+                new HandlerDispatcher<>(userCallbackSink, handler);
+        DuckTypingDispatcher<CameraDeviceImpl.CaptureCallback, CaptureCallback> duckToSession
+                = new DuckTypingDispatcher<>(handlerPassthrough, CaptureCallback.class);
+        ArgumentReplacingDispatcher<CameraDeviceImpl.CaptureCallback, CameraCaptureSessionImpl>
                 replaceDeviceWithSession = new ArgumentReplacingDispatcher<>(duckToSession,
                         /*argumentIndex*/0, this);
 
-        BroadcastDispatcher<CameraDeviceImpl.CaptureListener> broadcaster =
-                new BroadcastDispatcher<CameraDeviceImpl.CaptureListener>(
+        BroadcastDispatcher<CameraDeviceImpl.CaptureCallback> broadcaster =
+                new BroadcastDispatcher<CameraDeviceImpl.CaptureCallback>(
                     replaceDeviceWithSession,
                     localSink);
 
-        return new ListenerProxies.DeviceCaptureListenerProxy(broadcaster);
+        return new CallbackProxies.DeviceCaptureCallbackProxy(broadcaster);
     }
 
     /**
      *
-     * Create an internal state listener, to be invoked on the mDeviceHandler
+     * Create an internal state callback, to be invoked on the mDeviceHandler
      *
      * <p>It has a few behaviors:
      * <ul>
@@ -443,10 +443,10 @@
      * </ul>
      * </p>
      * */
-    CameraDeviceImpl.StateListenerKK getDeviceStateListener() {
+    CameraDeviceImpl.StateCallbackKK getDeviceStateCallback() {
         final CameraCaptureSession session = this;
 
-        return new CameraDeviceImpl.StateListenerKK() {
+        return new CameraDeviceImpl.StateCallbackKK() {
             private boolean mBusy = false;
             private boolean mActive = false;
 
@@ -471,7 +471,7 @@
                 mIdleDrainer.taskStarted();
                 mActive = true;
 
-                mStateListener.onActive(session);
+                mStateCallback.onActive(session);
             }
 
             @Override
@@ -507,7 +507,7 @@
                 mBusy = false;
                 mActive = false;
 
-                mStateListener.onReady(session);
+                mStateCallback.onReady(session);
             }
 
             @Override
@@ -629,7 +629,7 @@
 
                 // Fast path: A new capture session has replaced this one; don't unconfigure.
                 if (mSkipUnconfigure) {
-                    mStateListener.onClosed(CameraCaptureSessionImpl.this);
+                    mStateCallback.onClosed(CameraCaptureSessionImpl.this);
                     return;
                 }
 
@@ -655,7 +655,7 @@
         public void onDrained() {
             synchronized (CameraCaptureSessionImpl.this) {
                 // The device has finished unconfiguring. It's now fully closed.
-                mStateListener.onClosed(CameraCaptureSessionImpl.this);
+                mStateCallback.onClosed(CameraCaptureSessionImpl.this);
             }
         }
     }
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index f5666bf..d454092 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -64,17 +64,17 @@
     private final Object mInterfaceLock = new Object();
     private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();
 
-    private final StateListener mDeviceListener;
-    private volatile StateListenerKK mSessionStateListener;
+    private final StateCallback mDeviceCallback;
+    private volatile StateCallbackKK mSessionStateCallback;
     private final Handler mDeviceHandler;
 
     private volatile boolean mClosing = false;
     private boolean mInError = false;
     private boolean mIdle = true;
 
-    /** map request IDs to listener/request data */
-    private final SparseArray<CaptureListenerHolder> mCaptureListenerMap =
-            new SparseArray<CaptureListenerHolder>();
+    /** map request IDs to callback/request data */
+    private final SparseArray<CaptureCallbackHolder> mCaptureCallbackMap =
+            new SparseArray<CaptureCallbackHolder>();
 
     private int mRepeatingRequestId = REQUEST_ID_NONE;
     private final ArrayList<Integer> mRepeatingRequestIdDeletedList = new ArrayList<Integer>();
@@ -106,30 +106,30 @@
     private final Runnable mCallOnOpened = new Runnable() {
         @Override
         public void run() {
-            StateListenerKK sessionListener = null;
+            StateCallbackKK sessionCallback = null;
             synchronized(mInterfaceLock) {
                 if (mRemoteDevice == null) return; // Camera already closed
 
-                sessionListener = mSessionStateListener;
+                sessionCallback = mSessionStateCallback;
             }
-            if (sessionListener != null) {
-                sessionListener.onOpened(CameraDeviceImpl.this);
+            if (sessionCallback != null) {
+                sessionCallback.onOpened(CameraDeviceImpl.this);
             }
-            mDeviceListener.onOpened(CameraDeviceImpl.this);
+            mDeviceCallback.onOpened(CameraDeviceImpl.this);
         }
     };
 
     private final Runnable mCallOnUnconfigured = new Runnable() {
         @Override
         public void run() {
-            StateListenerKK sessionListener = null;
+            StateCallbackKK sessionCallback = null;
             synchronized(mInterfaceLock) {
                 if (mRemoteDevice == null) return; // Camera already closed
 
-                sessionListener = mSessionStateListener;
+                sessionCallback = mSessionStateCallback;
             }
-            if (sessionListener != null) {
-                sessionListener.onUnconfigured(CameraDeviceImpl.this);
+            if (sessionCallback != null) {
+                sessionCallback.onUnconfigured(CameraDeviceImpl.this);
             }
         }
     };
@@ -137,14 +137,14 @@
     private final Runnable mCallOnActive = new Runnable() {
         @Override
         public void run() {
-            StateListenerKK sessionListener = null;
+            StateCallbackKK sessionCallback = null;
             synchronized(mInterfaceLock) {
                 if (mRemoteDevice == null) return; // Camera already closed
 
-                sessionListener = mSessionStateListener;
+                sessionCallback = mSessionStateCallback;
             }
-            if (sessionListener != null) {
-                sessionListener.onActive(CameraDeviceImpl.this);
+            if (sessionCallback != null) {
+                sessionCallback.onActive(CameraDeviceImpl.this);
             }
         }
     };
@@ -152,14 +152,14 @@
     private final Runnable mCallOnBusy = new Runnable() {
         @Override
         public void run() {
-            StateListenerKK sessionListener = null;
+            StateCallbackKK sessionCallback = null;
             synchronized(mInterfaceLock) {
                 if (mRemoteDevice == null) return; // Camera already closed
 
-                sessionListener = mSessionStateListener;
+                sessionCallback = mSessionStateCallback;
             }
-            if (sessionListener != null) {
-                sessionListener.onBusy(CameraDeviceImpl.this);
+            if (sessionCallback != null) {
+                sessionCallback.onBusy(CameraDeviceImpl.this);
             }
         }
     };
@@ -172,14 +172,14 @@
             if (mClosedOnce) {
                 throw new AssertionError("Don't post #onClosed more than once");
             }
-            StateListenerKK sessionListener = null;
+            StateCallbackKK sessionCallback = null;
             synchronized(mInterfaceLock) {
-                sessionListener = mSessionStateListener;
+                sessionCallback = mSessionStateCallback;
             }
-            if (sessionListener != null) {
-                sessionListener.onClosed(CameraDeviceImpl.this);
+            if (sessionCallback != null) {
+                sessionCallback.onClosed(CameraDeviceImpl.this);
             }
-            mDeviceListener.onClosed(CameraDeviceImpl.this);
+            mDeviceCallback.onClosed(CameraDeviceImpl.this);
             mClosedOnce = true;
         }
     };
@@ -187,14 +187,14 @@
     private final Runnable mCallOnIdle = new Runnable() {
         @Override
         public void run() {
-            StateListenerKK sessionListener = null;
+            StateCallbackKK sessionCallback = null;
             synchronized(mInterfaceLock) {
                 if (mRemoteDevice == null) return; // Camera already closed
 
-                sessionListener = mSessionStateListener;
+                sessionCallback = mSessionStateCallback;
             }
-            if (sessionListener != null) {
-                sessionListener.onIdle(CameraDeviceImpl.this);
+            if (sessionCallback != null) {
+                sessionCallback.onIdle(CameraDeviceImpl.this);
             }
         }
     };
@@ -202,26 +202,26 @@
     private final Runnable mCallOnDisconnected = new Runnable() {
         @Override
         public void run() {
-            StateListenerKK sessionListener = null;
+            StateCallbackKK sessionCallback = null;
             synchronized(mInterfaceLock) {
                 if (mRemoteDevice == null) return; // Camera already closed
 
-                sessionListener = mSessionStateListener;
+                sessionCallback = mSessionStateCallback;
             }
-            if (sessionListener != null) {
-                sessionListener.onDisconnected(CameraDeviceImpl.this);
+            if (sessionCallback != null) {
+                sessionCallback.onDisconnected(CameraDeviceImpl.this);
             }
-            mDeviceListener.onDisconnected(CameraDeviceImpl.this);
+            mDeviceCallback.onDisconnected(CameraDeviceImpl.this);
         }
     };
 
-    public CameraDeviceImpl(String cameraId, StateListener listener, Handler handler,
+    public CameraDeviceImpl(String cameraId, StateCallback callback, Handler handler,
                         CameraCharacteristics characteristics) {
-        if (cameraId == null || listener == null || handler == null || characteristics == null) {
+        if (cameraId == null || callback == null || handler == null || characteristics == null) {
             throw new IllegalArgumentException("Null argument given");
         }
         mCameraId = cameraId;
-        mDeviceListener = listener;
+        mDeviceCallback = callback;
         mDeviceHandler = handler;
         mCharacteristics = characteristics;
 
@@ -263,28 +263,28 @@
     /**
      * Call to indicate failed connection to a remote camera device.
      *
-     * <p>This places the camera device in the error state and informs the listener.
+     * <p>This places the camera device in the error state and informs the callback.
      * Use in place of setRemoteDevice() when startup fails.</p>
      */
     public void setRemoteFailure(final CameraRuntimeException failure) {
-        int failureCode = StateListener.ERROR_CAMERA_DEVICE;
+        int failureCode = StateCallback.ERROR_CAMERA_DEVICE;
         boolean failureIsError = true;
 
         switch (failure.getReason()) {
             case CameraAccessException.CAMERA_IN_USE:
-                failureCode = StateListener.ERROR_CAMERA_IN_USE;
+                failureCode = StateCallback.ERROR_CAMERA_IN_USE;
                 break;
             case CameraAccessException.MAX_CAMERAS_IN_USE:
-                failureCode = StateListener.ERROR_MAX_CAMERAS_IN_USE;
+                failureCode = StateCallback.ERROR_MAX_CAMERAS_IN_USE;
                 break;
             case CameraAccessException.CAMERA_DISABLED:
-                failureCode = StateListener.ERROR_CAMERA_DISABLED;
+                failureCode = StateCallback.ERROR_CAMERA_DISABLED;
                 break;
             case CameraAccessException.CAMERA_DISCONNECTED:
                 failureIsError = false;
                 break;
             case CameraAccessException.CAMERA_ERROR:
-                failureCode = StateListener.ERROR_CAMERA_DEVICE;
+                failureCode = StateCallback.ERROR_CAMERA_DEVICE;
                 break;
             default:
                 Log.wtf(TAG, "Unknown failure in opening camera device: " + failure.getReason());
@@ -298,9 +298,9 @@
                 @Override
                 public void run() {
                     if (isError) {
-                        mDeviceListener.onError(CameraDeviceImpl.this, code);
+                        mDeviceCallback.onError(CameraDeviceImpl.this, code);
                     } else {
-                        mDeviceListener.onDisconnected(CameraDeviceImpl.this);
+                        mDeviceCallback.onDisconnected(CameraDeviceImpl.this);
                     }
                 }
             });
@@ -415,7 +415,7 @@
 
     @Override
     public void createCaptureSession(List<Surface> outputs,
-            CameraCaptureSession.StateListener listener, Handler handler)
+            CameraCaptureSession.StateCallback callback, Handler handler)
             throws CameraAccessException {
         synchronized(mInterfaceLock) {
             if (DEBUG) {
@@ -445,7 +445,7 @@
 
             // Fire onConfigured if configureOutputs succeeded, fire onConfigureFailed otherwise.
             CameraCaptureSessionImpl newSession =
-                    new CameraCaptureSessionImpl(outputs, listener, handler, this, mDeviceHandler,
+                    new CameraCaptureSessionImpl(outputs, callback, handler, this, mDeviceHandler,
                             configureSuccess);
 
             // TODO: wait until current session closes, then create the new session
@@ -455,16 +455,16 @@
                 throw pendingException;
             }
 
-            mSessionStateListener = mCurrentSession.getDeviceStateListener();
+            mSessionStateCallback = mCurrentSession.getDeviceStateCallback();
         }
     }
 
     /**
      * For use by backwards-compatibility code only.
      */
-    public void setSessionListener(StateListenerKK sessionListener) {
+    public void setSessionListener(StateCallbackKK sessionCallback) {
         synchronized(mInterfaceLock) {
-            mSessionStateListener = sessionListener;
+            mSessionStateCallback = sessionCallback;
         }
     }
 
@@ -492,22 +492,22 @@
         }
     }
 
-    public int capture(CaptureRequest request, CaptureListener listener, Handler handler)
+    public int capture(CaptureRequest request, CaptureCallback callback, Handler handler)
             throws CameraAccessException {
         if (DEBUG) {
             Log.d(TAG, "calling capture");
         }
         List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
         requestList.add(request);
-        return submitCaptureRequest(requestList, listener, handler, /*streaming*/false);
+        return submitCaptureRequest(requestList, callback, handler, /*streaming*/false);
     }
 
-    public int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
+    public int captureBurst(List<CaptureRequest> requests, CaptureCallback callback,
             Handler handler) throws CameraAccessException {
         if (requests == null || requests.isEmpty()) {
             throw new IllegalArgumentException("At least one request must be given");
         }
-        return submitCaptureRequest(requests, listener, handler, /*streaming*/false);
+        return submitCaptureRequest(requests, callback, handler, /*streaming*/false);
     }
 
     /**
@@ -527,12 +527,12 @@
             final int requestId, final long lastFrameNumber) {
         // lastFrameNumber being equal to NO_FRAMES_CAPTURED means that the request
         // was never sent to HAL. Should trigger onCaptureSequenceAborted immediately.
-        if (lastFrameNumber == CaptureListener.NO_FRAMES_CAPTURED) {
-            final CaptureListenerHolder holder;
-            int index = mCaptureListenerMap.indexOfKey(requestId);
-            holder = (index >= 0) ? mCaptureListenerMap.valueAt(index) : null;
+        if (lastFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
+            final CaptureCallbackHolder holder;
+            int index = mCaptureCallbackMap.indexOfKey(requestId);
+            holder = (index >= 0) ? mCaptureCallbackMap.valueAt(index) : null;
             if (holder != null) {
-                mCaptureListenerMap.removeAt(index);
+                mCaptureCallbackMap.removeAt(index);
                 if (DEBUG) {
                     Log.v(TAG, String.format(
                             "remove holder for requestId %d, "
@@ -560,7 +560,7 @@
                                     || lastFrameNumber > Integer.MAX_VALUE) {
                                 throw new AssertionError(lastFrameNumber + " cannot be cast to int");
                             }
-                            holder.getListener().onCaptureSequenceAborted(
+                            holder.getCallback().onCaptureSequenceAborted(
                                     CameraDeviceImpl.this,
                                     requestId);
                         }
@@ -569,7 +569,7 @@
                 holder.getHandler().post(resultDispatch);
             } else {
                 Log.w(TAG, String.format(
-                        "did not register listener to request %d",
+                        "did not register callback to request %d",
                         requestId));
             }
         } else {
@@ -579,12 +579,12 @@
         }
     }
 
-    private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureListener listener,
+    private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureCallback callback,
             Handler handler, boolean repeating) throws CameraAccessException {
 
         // Need a valid handler, or current thread needs to have a looper, if
-        // listener is valid
-        handler = checkHandler(handler, listener);
+        // callback is valid
+        handler = checkHandler(handler, callback);
 
         // Make sure that there all requests have at least 1 surface; all surfaces are non-null
         for (CaptureRequest request : requestList) {
@@ -622,8 +622,8 @@
                 return -1;
             }
 
-            if (listener != null) {
-                mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener,
+            if (callback != null) {
+                mCaptureCallbackMap.put(requestId, new CaptureCallbackHolder(callback,
                         requestList, handler, repeating));
             } else {
                 if (DEBUG) {
@@ -652,19 +652,19 @@
         }
     }
 
-    public int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
+    public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
             Handler handler) throws CameraAccessException {
         List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
         requestList.add(request);
-        return submitCaptureRequest(requestList, listener, handler, /*streaming*/true);
+        return submitCaptureRequest(requestList, callback, handler, /*streaming*/true);
     }
 
-    public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
+    public int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback callback,
             Handler handler) throws CameraAccessException {
         if (requests == null || requests.isEmpty()) {
             throw new IllegalArgumentException("At least one request must be given");
         }
-        return submitCaptureRequest(requests, listener, handler, /*streaming*/true);
+        return submitCaptureRequest(requests, callback, handler, /*streaming*/true);
     }
 
     public void stopRepeating() throws CameraAccessException {
@@ -677,7 +677,7 @@
                 mRepeatingRequestId = REQUEST_ID_NONE;
 
                 // Queue for deletion after in-flight requests finish
-                if (mCaptureListenerMap.get(requestId) != null) {
+                if (mCaptureCallbackMap.get(requestId) != null) {
                     mRepeatingRequestIdDeletedList.add(requestId);
                 }
 
@@ -782,11 +782,11 @@
     }
 
     /**
-     * <p>A listener for tracking the progress of a {@link CaptureRequest}
+     * <p>A callback for tracking the progress of a {@link CaptureRequest}
      * submitted to the camera device.</p>
      *
      */
-    public static abstract class CaptureListener {
+    public static abstract class CaptureCallback {
 
         /**
          * This constant is used to indicate that no images were captured for
@@ -848,9 +848,9 @@
         }
 
         /**
-         * This method is called independently of the others in CaptureListener,
+         * This method is called independently of the others in CaptureCallback,
          * when a capture sequence finishes and all {@link CaptureResult}
-         * or {@link CaptureFailure} for it have been returned via this listener.
+         * or {@link CaptureFailure} for it have been returned via this callback.
          */
         public void onCaptureSequenceCompleted(CameraDevice camera,
                 int sequenceId, long frameNumber) {
@@ -858,9 +858,9 @@
         }
 
         /**
-         * This method is called independently of the others in CaptureListener,
+         * This method is called independently of the others in CaptureCallback,
          * when a capture sequence aborts before any {@link CaptureResult}
-         * or {@link CaptureFailure} for it have been returned via this listener.
+         * or {@link CaptureFailure} for it have been returned via this callback.
          */
         public void onCaptureSequenceAborted(CameraDevice camera,
                 int sequenceId) {
@@ -869,10 +869,10 @@
     }
 
     /**
-     * A listener for notifications about the state of a camera device, adding in the callbacks that
+     * A callback for notifications about the state of a camera device, adding in the callbacks that
      * were part of the earlier KK API design, but now only used internally.
      */
-    public static abstract class StateListenerKK extends StateListener {
+    public static abstract class StateCallbackKK extends StateCallback {
         /**
          * The method called when a camera device has no outputs configured.
          *
@@ -908,31 +908,31 @@
         }
     }
 
-    static class CaptureListenerHolder {
+    static class CaptureCallbackHolder {
 
         private final boolean mRepeating;
-        private final CaptureListener mListener;
+        private final CaptureCallback mCallback;
         private final List<CaptureRequest> mRequestList;
         private final Handler mHandler;
 
-        CaptureListenerHolder(CaptureListener listener, List<CaptureRequest> requestList,
+        CaptureCallbackHolder(CaptureCallback callback, List<CaptureRequest> requestList,
                 Handler handler, boolean repeating) {
-            if (listener == null || handler == null) {
+            if (callback == null || handler == null) {
                 throw new UnsupportedOperationException(
-                    "Must have a valid handler and a valid listener");
+                    "Must have a valid handler and a valid callback");
             }
             mRepeating = repeating;
             mHandler = handler;
             mRequestList = new ArrayList<CaptureRequest>(requestList);
-            mListener = listener;
+            mCallback = callback;
         }
 
         public boolean isRepeating() {
             return mRepeating;
         }
 
-        public CaptureListener getListener() {
-            return mListener;
+        public CaptureCallback getCallback() {
+            return mCallback;
         }
 
         public CaptureRequest getRequest(int subsequenceId) {
@@ -1071,20 +1071,20 @@
             final SimpleEntry<Long, Integer> frameNumberRequestPair = iter.next();
             if (frameNumberRequestPair.getKey() <= completedFrameNumber) {
 
-                // remove request from mCaptureListenerMap
+                // remove request from mCaptureCallbackMap
                 final int requestId = frameNumberRequestPair.getValue();
-                final CaptureListenerHolder holder;
+                final CaptureCallbackHolder holder;
                 synchronized(mInterfaceLock) {
                     if (mRemoteDevice == null) {
                         Log.w(TAG, "Camera closed while checking sequences");
                         return;
                     }
 
-                    int index = mCaptureListenerMap.indexOfKey(requestId);
-                    holder = (index >= 0) ? mCaptureListenerMap.valueAt(index)
+                    int index = mCaptureCallbackMap.indexOfKey(requestId);
+                    holder = (index >= 0) ? mCaptureCallbackMap.valueAt(index)
                             : null;
                     if (holder != null) {
-                        mCaptureListenerMap.removeAt(index);
+                        mCaptureCallbackMap.removeAt(index);
                         if (DEBUG) {
                             Log.v(TAG, String.format(
                                     "remove holder for requestId %d, "
@@ -1114,7 +1114,7 @@
                                     throw new AssertionError(lastFrameNumber
                                             + " cannot be cast to int");
                                 }
-                                holder.getListener().onCaptureSequenceCompleted(
+                                holder.getCallback().onCaptureSequenceCompleted(
                                     CameraDeviceImpl.this,
                                     requestId,
                                     lastFrameNumber);
@@ -1146,13 +1146,13 @@
 
         /**
          * Camera has encountered a device-level error
-         * Matches CameraDevice.StateListener#ERROR_CAMERA_DEVICE
+         * Matches CameraDevice.StateCallback#ERROR_CAMERA_DEVICE
          */
         static final int ERROR_CAMERA_DEVICE = 1;
 
         /**
          * Camera has encountered a service-level error
-         * Matches CameraDevice.StateListener#ERROR_CAMERA_SERVICE
+         * Matches CameraDevice.StateCallback#ERROR_CAMERA_SERVICE
          */
         static final int ERROR_CAMERA_SERVICE = 2;
 
@@ -1204,7 +1204,7 @@
                             @Override
                             public void run() {
                                 if (!CameraDeviceImpl.this.isClosed()) {
-                                    mDeviceListener.onError(CameraDeviceImpl.this, errorCode);
+                                    mDeviceCallback.onError(CameraDeviceImpl.this, errorCode);
                                 }
                             }
                         };
@@ -1240,13 +1240,13 @@
             if (DEBUG) {
                 Log.d(TAG, "Capture started for id " + requestId);
             }
-            final CaptureListenerHolder holder;
+            final CaptureCallbackHolder holder;
 
             synchronized(mInterfaceLock) {
                 if (mRemoteDevice == null) return; // Camera already closed
 
-                // Get the listener for this frame ID, if there is one
-                holder = CameraDeviceImpl.this.mCaptureListenerMap.get(requestId);
+                // Get the callback for this frame ID, if there is one
+                holder = CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId);
 
                 if (holder == null) {
                     return;
@@ -1260,7 +1260,7 @@
                         @Override
                         public void run() {
                             if (!CameraDeviceImpl.this.isClosed()) {
-                                holder.getListener().onCaptureStarted(
+                                holder.getCallback().onCaptureStarted(
                                     CameraDeviceImpl.this,
                                     holder.getRequest(resultExtras.getSubsequenceId()),
                                     timestamp);
@@ -1290,13 +1290,13 @@
                 result.set(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE,
                         getCharacteristics().get(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE));
 
-                final CaptureListenerHolder holder =
-                        CameraDeviceImpl.this.mCaptureListenerMap.get(requestId);
+                final CaptureCallbackHolder holder =
+                        CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId);
 
                 boolean isPartialResult =
                         (resultExtras.getPartialResultCount() < mTotalPartialCount);
 
-                // Check if we have a listener for this
+                // Check if we have a callback for this
                 if (holder == null) {
                     if (DEBUG) {
                         Log.d(TAG,
@@ -1336,7 +1336,7 @@
                         @Override
                         public void run() {
                             if (!CameraDeviceImpl.this.isClosed()){
-                                holder.getListener().onCaptureProgressed(
+                                holder.getCallback().onCaptureProgressed(
                                     CameraDeviceImpl.this,
                                     request,
                                     resultAsCapture);
@@ -1357,7 +1357,7 @@
                         @Override
                         public void run() {
                             if (!CameraDeviceImpl.this.isClosed()){
-                                holder.getListener().onCaptureCompleted(
+                                holder.getCallback().onCaptureCompleted(
                                     CameraDeviceImpl.this,
                                     request,
                                     resultAsCapture);
@@ -1388,8 +1388,8 @@
             final int requestId = resultExtras.getRequestId();
             final int subsequenceId = resultExtras.getSubsequenceId();
             final long frameNumber = resultExtras.getFrameNumber();
-            final CaptureListenerHolder holder =
-                    CameraDeviceImpl.this.mCaptureListenerMap.get(requestId);
+            final CaptureCallbackHolder holder =
+                    CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId);
 
             final CaptureRequest request = holder.getRequest(subsequenceId);
 
@@ -1420,7 +1420,7 @@
                 @Override
                 public void run() {
                     if (!CameraDeviceImpl.this.isClosed()){
-                        holder.getListener().onCaptureFailed(
+                        holder.getCallback().onCaptureFailed(
                             CameraDeviceImpl.this,
                             request,
                             failure);
@@ -1460,12 +1460,12 @@
     }
 
     /**
-     * Default handler management, conditional on there being a listener.
+     * Default handler management, conditional on there being a callback.
      *
-     * <p>If the listener isn't null, check the handler, otherwise pass it through.</p>
+     * <p>If the callback isn't null, check the handler, otherwise pass it through.</p>
      */
-    static <T> Handler checkHandler(Handler handler, T listener) {
-        if (listener != null) {
+    static <T> Handler checkHandler(Handler handler, T callback) {
+        if (callback != null) {
             return checkHandler(handler);
         }
         return handler;
diff --git a/core/java/android/hardware/camera2/legacy/GLThreadManager.java b/core/java/android/hardware/camera2/legacy/GLThreadManager.java
index 06521cf..2c584ef 100644
--- a/core/java/android/hardware/camera2/legacy/GLThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/GLThreadManager.java
@@ -121,9 +121,10 @@
      * Create a new GL thread and renderer.
      *
      * @param cameraId the camera id for this thread.
+     * @param facing direction the camera is facing.
      */
-    public GLThreadManager(int cameraId) {
-        mTextureRenderer = new SurfaceTextureRenderer();
+    public GLThreadManager(int cameraId, int facing) {
+        mTextureRenderer = new SurfaceTextureRenderer(facing);
         TAG = String.format("CameraDeviceGLThread-%d", cameraId);
         mGLHandlerThread = new RequestHandlerThread(TAG, mGLHandlerCb);
     }
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index eb8debb..e6ff17b 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -399,7 +399,7 @@
 
         // TODO: Detect and optimize single-output paths here to skip stream teeing.
         if (mGLThreadManager == null) {
-            mGLThreadManager = new GLThreadManager(mCameraId);
+            mGLThreadManager = new GLThreadManager(mCameraId, facing);
             mGLThreadManager.start();
         }
         mGLThreadManager.waitUntilStarted();
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
index b1b0f9b..a35883c 100644
--- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -18,6 +18,7 @@
 import android.graphics.ImageFormat;
 import android.graphics.RectF;
 import android.graphics.SurfaceTexture;
+import android.hardware.camera2.CameraCharacteristics;
 import android.os.Environment;
 import android.opengl.EGL14;
 import android.opengl.EGLConfig;
@@ -80,7 +81,18 @@
     private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
     private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
     private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
-    private final float[] mTriangleVerticesData = {
+
+    // Sampling is mirrored across the vertical axis to undo horizontal flip from the front camera
+    private static final float[] sFrontCameraTriangleVertices = {
+            // X, Y, Z, U, V
+            -1.0f, -1.0f, 0, 1.f, 0.f,
+            1.0f, -1.0f, 0, 0.f, 0.f,
+            -1.0f,  1.0f, 0, 1.f, 1.f,
+            1.0f,  1.0f, 0, 0.f, 1.f,
+    };
+
+    // Sampling is 1:1 for a straight copy for the back camera
+    private static final float[] sBackCameraTriangleVertices = {
             // X, Y, Z, U, V
             -1.0f, -1.0f, 0, 0.f, 0.f,
             1.0f, -1.0f, 0, 1.f, 0.f,
@@ -135,10 +147,16 @@
     private PerfMeasurement mPerfMeasurer = null;
     private static final String LEGACY_PERF_PROPERTY = "persist.camera.legacy_perf";
 
-    public SurfaceTextureRenderer() {
-        mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length *
-                FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
-        mTriangleVertices.put(mTriangleVerticesData).position(0);
+    public SurfaceTextureRenderer(int facing) {
+        if (facing == CameraCharacteristics.LENS_FACING_BACK) {
+            mTriangleVertices = ByteBuffer.allocateDirect(sBackCameraTriangleVertices.length *
+                    FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
+            mTriangleVertices.put(sBackCameraTriangleVertices).position(0);
+        } else {
+            mTriangleVertices = ByteBuffer.allocateDirect(sFrontCameraTriangleVertices.length *
+                    FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
+            mTriangleVertices.put(sFrontCameraTriangleVertices).position(0);
+        }
         Matrix.setIdentityM(mSTMatrix, 0);
     }
 
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 7a49eb5..7390e2b 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -480,7 +480,7 @@
             int capturePreambleMs = in.readInt();
             boolean triggerInData = in.readByte() == 1;
             AudioFormat captureFormat = null;
-            if (triggerInData) {
+            if (in.readByte() == 1) {
                 int sampleRate = in.readInt();
                 int encoding = in.readInt();
                 int channelMask = in.readInt();
@@ -508,7 +508,8 @@
             dest.writeInt(captureSession);
             dest.writeInt(captureDelayMs);
             dest.writeInt(capturePreambleMs);
-            if (triggerInData && (captureFormat != null)) {
+            dest.writeByte((byte) (triggerInData ? 1 : 0));
+            if (captureFormat != null) {
                 dest.writeByte((byte)1);
                 dest.writeInt(captureFormat.getSampleRate());
                 dest.writeInt(captureFormat.getEncoding());
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index fe9f79b..461469c 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1667,7 +1667,7 @@
      */
     public abstract long[] getChargeStepDurationsArray();
 
-    public abstract Map<String, ? extends LongCounter> getWakeupReasonStats();
+    public abstract Map<String, ? extends Timer> getWakeupReasonStats();
 
     public abstract Map<String, ? extends Timer> getKernelWakelockStats();
 
@@ -2045,11 +2045,15 @@
                             sb.toString());
                 }
             }
-            Map<String, ? extends LongCounter> wakeupReasons = getWakeupReasonStats();
+            Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
             if (wakeupReasons.size() > 0) {
-                for (Map.Entry<String, ? extends LongCounter> ent : wakeupReasons.entrySet()) {
+                for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
+                    // Not doing the regular wake lock formatting to remain compatible
+                    // with the old checkin format.
+                    long totalTimeMicros = ent.getValue().getTotalTimeLocked(rawRealtime, which);
+                    int count = ent.getValue().getCountLocked(which);
                     dumpLine(pw, 0 /* uid */, category, WAKEUP_REASON_DATA,
-                            "\"" + ent.getKey() + "\"", ent.getValue().getCountLocked(which));
+                            "\"" + ent.getKey() + "\"", (totalTimeMicros + 500) / 1000, count);
                 }
             }
         }
@@ -2921,14 +2925,14 @@
                 pw.println();
             }
 
-            Map<String, ? extends LongCounter> wakeupReasons = getWakeupReasonStats();
+            Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
             if (wakeupReasons.size() > 0) {
                 pw.print(prefix); pw.println("  All wakeup reasons:");
                 final ArrayList<TimerEntry> reasons = new ArrayList<TimerEntry>();
-                for (Map.Entry<String, ? extends LongCounter> ent : wakeupReasons.entrySet()) {
-                    BatteryStats.LongCounter counter = ent.getValue();
-                    reasons.add(new TimerEntry(ent.getKey(), 0, null,
-                            ent.getValue().getCountLocked(which)));
+                for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
+                    Timer timer = ent.getValue();
+                    reasons.add(new TimerEntry(ent.getKey(), 0, timer,
+                            timer.getCountLocked(which)));
                 }
                 Collections.sort(reasons, timerComparator);
                 for (int i=0; i<reasons.size(); i++) {
@@ -2938,9 +2942,8 @@
                     sb.append(prefix);
                     sb.append("  Wakeup reason ");
                     sb.append(timer.mName);
-                    sb.append(": ");
-                    formatTimeMs(sb, timer.mTime);
-                    sb.append("realtime");
+                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
+                    sb.append(" realtime");
                     pw.println(sb.toString());
                 }
                 pw.println();
@@ -3138,7 +3141,7 @@
             }
 
             Map<String, ? extends Timer> jobs = u.getJobStats();
-            if (syncs.size() > 0) {
+            if (jobs.size() > 0) {
                 for (Map.Entry<String, ? extends Timer> ent : jobs.entrySet()) {
                     Timer timer = ent.getValue();
                     // Convert from microseconds to milliseconds with rounding
@@ -3952,7 +3955,7 @@
         prepareForDumpLocked();
 
         dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA,
-                "10", getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion());
+                "11", getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion());
 
         long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
 
diff --git a/core/java/android/os/FileBridge.java b/core/java/android/os/FileBridge.java
index 022a106..0acf24b 100644
--- a/core/java/android/os/FileBridge.java
+++ b/core/java/android/os/FileBridge.java
@@ -75,6 +75,13 @@
         return mClosed;
     }
 
+    public void forceClose() {
+        IoUtils.closeQuietly(mTarget);
+        IoUtils.closeQuietly(mServer);
+        IoUtils.closeQuietly(mClient);
+        mClosed = true;
+    }
+
     public void setTargetFile(FileDescriptor target) {
         mTarget = target;
     }
@@ -89,7 +96,6 @@
         try {
             while (IoBridge.read(mServer, temp, 0, MSG_LENGTH) == MSG_LENGTH) {
                 final int cmd = Memory.peekInt(temp, 0, ByteOrder.BIG_ENDIAN);
-
                 if (cmd == CMD_WRITE) {
                     // Shuttle data into local file
                     int len = Memory.peekInt(temp, 4, ByteOrder.BIG_ENDIAN);
@@ -118,15 +124,10 @@
                 }
             }
 
-        } catch (ErrnoException e) {
-            Log.wtf(TAG, "Failed during bridge", e);
-        } catch (IOException e) {
+        } catch (ErrnoException | IOException e) {
             Log.wtf(TAG, "Failed during bridge", e);
         } finally {
-            IoUtils.closeQuietly(mTarget);
-            IoUtils.closeQuietly(mServer);
-            IoUtils.closeQuietly(mClient);
-            mClosed = true;
+            forceClose();
         }
     }
 
@@ -151,6 +152,7 @@
                 writeCommandAndBlock(CMD_CLOSE, "close()");
             } finally {
                 IoBridge.closeAndSignalBlockedThreads(mClient);
+                IoUtils.closeQuietly(mClientPfd);
             }
         }
 
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 1a5811c..b6b70cc 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -113,6 +113,8 @@
 
     private static final int MAX_POOL_SIZE = 50;
 
+    private static boolean gCheckRecycle = true;
+
     /**
      * Return a new Message instance from the global pool. Allows us to
      * avoid allocating new objects in many cases.
@@ -256,6 +258,13 @@
         return m;
     }
 
+    /** @hide */
+    public static void updateCheckRecycle(int targetSdkVersion) {
+        if (targetSdkVersion < Build.VERSION_CODES.L) {
+            gCheckRecycle = false;
+        }
+    }
+
     /**
      * Return a Message instance to the global pool.
      * <p>
@@ -266,8 +275,11 @@
      */
     public void recycle() {
         if (isInUse()) {
-            throw new IllegalStateException("This message cannot be recycled because it "
-                    + "is still in use.");
+            if (gCheckRecycle) {
+                throw new IllegalStateException("This message cannot be recycled because it "
+                        + "is still in use.");
+            }
+            return;
         }
         recycleUnchecked();
     }
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 9361286..bf8ac65 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -535,7 +535,7 @@
                 destroyed = isDestroyedLocked();
             }
 
-            if (destroyed) {
+            if (destroyed && observer != null) {
                 try {
                     observer.onDestroy();
                 } catch (RemoteException re) {
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 8ca9b6c..e6bf6ba 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -16,6 +16,7 @@
 
 package android.service.notification;
 
+import android.service.notification.IStatusBarNotificationHolder;
 import android.service.notification.StatusBarNotification;
 import android.service.notification.NotificationRankingUpdate;
 
@@ -23,9 +24,9 @@
 oneway interface INotificationListener
 {
     void onListenerConnected(in NotificationRankingUpdate update);
-    void onNotificationPosted(in StatusBarNotification notification,
+    void onNotificationPosted(in IStatusBarNotificationHolder notificationHolder,
             in NotificationRankingUpdate update);
-    void onNotificationRemoved(in StatusBarNotification notification,
+    void onNotificationRemoved(in IStatusBarNotificationHolder notificationHolder,
             in NotificationRankingUpdate update);
     void onNotificationRankingUpdate(in NotificationRankingUpdate update);
     void onListenerHintsChanged(int hints);
diff --git a/core/java/android/service/notification/IStatusBarNotificationHolder.aidl b/core/java/android/service/notification/IStatusBarNotificationHolder.aidl
new file mode 100644
index 0000000..fd6b59e
--- /dev/null
+++ b/core/java/android/service/notification/IStatusBarNotificationHolder.aidl
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+import android.service.notification.StatusBarNotification;
+
+/** @hide */
+interface IStatusBarNotificationHolder {
+    StatusBarNotification get();
+}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 2ca8098..d744070 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -603,8 +603,15 @@
 
     private class INotificationListenerWrapper extends INotificationListener.Stub {
         @Override
-        public void onNotificationPosted(StatusBarNotification sbn,
+        public void onNotificationPosted(IStatusBarNotificationHolder sbnHolder,
                 NotificationRankingUpdate update) {
+            StatusBarNotification sbn;
+            try {
+                sbn = sbnHolder.get();
+            } catch (RemoteException e) {
+                Log.w(TAG, "onNotificationPosted: Error receiving StatusBarNotification", e);
+                return;
+            }
             Notification.Builder.rebuild(getContext(), sbn.getNotification());
 
             // protect subclass from concurrent modifications of (@link mNotificationKeys}.
@@ -618,8 +625,15 @@
             }
         }
         @Override
-        public void onNotificationRemoved(StatusBarNotification sbn,
+        public void onNotificationRemoved(IStatusBarNotificationHolder sbnHolder,
                 NotificationRankingUpdate update) {
+            StatusBarNotification sbn;
+            try {
+                sbn = sbnHolder.get();
+            } catch (RemoteException e) {
+                Log.w(TAG, "onNotificationRemoved: Error receiving StatusBarNotification", e);
+                return;
+            }
             // protect subclass from concurrent modifications of (@link mNotificationKeys}.
             synchronized (mWrapper) {
                 applyUpdate(update);
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 4de5f41..8aa2689 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -468,19 +468,6 @@
     }
 
     /**
-     * FIXME: Remove once the prebuilts are updated.
-     *
-     * @hide
-     */
-    @Deprecated
-    public Intent createIntentToEnroll() {
-        if (DBG) Slog.d(TAG, "createIntentToEnroll");
-        synchronized (mLock) {
-            return getManageIntentLocked(MANAGE_ACTION_ENROLL);
-        }
-    }
-
-    /**
      * Creates an intent to start the un-enrollment for the associated keyphrase.
      * This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
      * Starting re-enrollment is only valid if the keyphrase is already enrolled,
@@ -502,19 +489,6 @@
     }
 
     /**
-     * FIXME: Remove once the prebuilts are updated.
-     *
-     * @hide
-     */
-    @Deprecated
-    public Intent createIntentToUnEnroll() {
-        if (DBG) Slog.d(TAG, "createIntentToUnEnroll");
-        synchronized (mLock) {
-            return getManageIntentLocked(MANAGE_ACTION_UN_ENROLL);
-        }
-    }
-
-    /**
      * Creates an intent to start the re-enrollment for the associated keyphrase.
      * This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
      * Starting re-enrollment is only valid if the keyphrase is already enrolled,
@@ -535,19 +509,6 @@
         }
     }
 
-    /**
-     * FIXME: Remove once the prebuilts are updated.
-     *
-     * @hide
-     */
-    @Deprecated
-    public Intent createIntentToReEnroll() {
-        if (DBG) Slog.d(TAG, "createIntentToReEnroll");
-        synchronized (mLock) {
-            return getManageIntentLocked(MANAGE_ACTION_RE_ENROLL);
-        }
-    }
-
     private Intent getManageIntentLocked(int action) {
         if (mAvailability == STATE_INVALID) {
             throw new IllegalStateException("getManageIntent called on an invalid detector");
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 7245975..a4b6e92 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -578,7 +578,7 @@
          *
          * @deprecated Starting from API level 20, to select network synthesis, call
          * ({@link TextToSpeech#getVoices()}, find a suitable network voice
-         * ({@link Voice#getRequiresNetworkConnection()}) and pass it
+         * ({@link Voice#isNetworkConnectionRequired()}) and pass it
          * to {@link TextToSpeech#setVoice(Voice)}).
          */
         @Deprecated
@@ -596,7 +596,7 @@
 
          * @deprecated Starting from API level 20, to select embedded synthesis, call
          * ({@link TextToSpeech#getVoices()}, find a suitable embedded voice
-         * ({@link Voice#getRequiresNetworkConnection()}) and pass it
+         * ({@link Voice#isNetworkConnectionRequired()}) and pass it
          * to {@link TextToSpeech#setVoice(Voice)}).
          */
         @Deprecated
@@ -957,20 +957,18 @@
      *
      * @param text
      *            The string of text. Example: <code>"south_south_east"</code>
-     * @param filename
-     *            The full path to the sound file (for example:
-     *            "/sdcard/mysounds/hello.wav")
+     * @param file
+     *            File object pointing to the sound file.
      *
      * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
      */
-    public int addSpeech(CharSequence text, String filename) {
+    public int addSpeech(CharSequence text, File file) {
         synchronized (mStartLock) {
-            mUtterances.put(text, Uri.parse(filename));
+            mUtterances.put(text, Uri.fromFile(file));
             return SUCCESS;
         }
     }
 
-
     /**
      * Adds a mapping between a string of text and a sound resource in a
      * package. Use this to add custom earcons.
@@ -1017,7 +1015,11 @@
      *            "/sdcard/mysounds/tick.wav")
      *
      * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
+     *
+     * @deprecated As of API level 20, replaced by
+     *         {@link #addEarcon(String, File)}.
      */
+    @Deprecated
     public int addEarcon(String earcon, String filename) {
         synchronized(mStartLock) {
             mEarcons.put(earcon, Uri.parse(filename));
@@ -1025,6 +1027,27 @@
         }
     }
 
+    /**
+     * Adds a mapping between a string of text and a sound file.
+     * Use this to add custom earcons.
+     *
+     * @see #playEarcon(String, int, HashMap)
+     *
+     * @param earcon
+     *            The name of the earcon.
+     *            Example: <code>"[tick]"</code>
+     * @param file
+     *            File object pointing to the sound file.
+     *
+     * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
+     */
+    public int addEarcon(String earcon, File file) {
+        synchronized(mStartLock) {
+            mEarcons.put(earcon, Uri.fromFile(file));
+            return SUCCESS;
+        }
+    }
+
     private Uri makeResourceUri(String packageName, int resourceId) {
         return new Uri.Builder()
                 .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
@@ -1061,7 +1084,7 @@
      */
     public int speak(final CharSequence text,
                      final int queueMode,
-                     final HashMap<String, String> params,
+                     final Bundle params,
                      final String utteranceId) {
         return runAction(new Action<Integer>() {
             @Override
@@ -1103,11 +1126,11 @@
      *
      * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the speak operation.
      * @deprecated As of API level 20, replaced by
-     *         {@link #speak(CharSequence, int, HashMap, String)}.
+     *         {@link #speak(CharSequence, int, Bundle, String)}.
      */
     @Deprecated
     public int speak(final String text, final int queueMode, final HashMap<String, String> params) {
-        return speak(text, queueMode, params,
+        return speak(text, queueMode, convertParamsHashMaptoBundle(params),
                      params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID));
     }
 
@@ -1135,7 +1158,7 @@
      * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation.
      */
     public int playEarcon(final String earcon, final int queueMode,
-            final HashMap<String, String> params, final String utteranceId) {
+            final Bundle params, final String utteranceId) {
         return runAction(new Action<Integer>() {
             @Override
             public Integer run(ITextToSpeechService service) throws RemoteException {
@@ -1173,12 +1196,12 @@
      *
      * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation.
      * @deprecated As of API level 20, replaced by
-     *         {@link #playEarcon(String, int, HashMap, String)}.
+     *         {@link #playEarcon(String, int, Bundle, String)}.
      */
     @Deprecated
     public int playEarcon(final String earcon, final int queueMode,
             final HashMap<String, String> params) {
-        return playEarcon(earcon, queueMode, params,
+        return playEarcon(earcon, queueMode, convertParamsHashMaptoBundle(params),
                           params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID));
     }
 
@@ -1757,22 +1780,20 @@
      *            must be prefixed by the name of the engine they are intended for. For example
      *            the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
      *            engine named "com.svox.pico" if it is being used.
-     * @param filename Absolute file filename to write the generated audio data to.It should be
-     *            something like "/sdcard/myappsounds/mysound.wav".
+     * @param file File to write the generated audio data to.
      * @param utteranceId An unique identifier for this request.
      * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation.
      */
-    public int synthesizeToFile(final CharSequence text, final HashMap<String, String> params,
-            final String filename, final String utteranceId) {
+    public int synthesizeToFile(final CharSequence text, final Bundle params,
+            final File file, final String utteranceId) {
         return runAction(new Action<Integer>() {
             @Override
             public Integer run(ITextToSpeechService service) throws RemoteException {
                 ParcelFileDescriptor fileDescriptor;
                 int returnValue;
                 try {
-                    File file = new File(filename);
                     if(file.exists() && !file.canWrite()) {
-                        Log.e(TAG, "Can't write to " + filename);
+                        Log.e(TAG, "Can't write to " + file);
                         return ERROR;
                     }
                     fileDescriptor = ParcelFileDescriptor.open(file,
@@ -1784,10 +1805,10 @@
                     fileDescriptor.close();
                     return returnValue;
                 } catch (FileNotFoundException e) {
-                    Log.e(TAG, "Opening file " + filename + " failed", e);
+                    Log.e(TAG, "Opening file " + file + " failed", e);
                     return ERROR;
                 } catch (IOException e) {
-                    Log.e(TAG, "Closing file " + filename + " failed", e);
+                    Log.e(TAG, "Closing file " + file + " failed", e);
                     return ERROR;
                 }
             }
@@ -1817,16 +1838,18 @@
      *
      * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation.
      * @deprecated As of API level 20, replaced by
-     *         {@link #synthesizeToFile(CharSequence, HashMap, String, String)}.
+     *         {@link #synthesizeToFile(CharSequence, Bundle, File, String)}.
      */
+    @Deprecated
     public int synthesizeToFile(final String text, final HashMap<String, String> params,
             final String filename) {
-        return synthesizeToFile(text, params, filename, params.get(Engine.KEY_PARAM_UTTERANCE_ID));
+        return synthesizeToFile(text, convertParamsHashMaptoBundle(params),
+                new File(filename), params.get(Engine.KEY_PARAM_UTTERANCE_ID));
     }
 
-    private Bundle getParams(HashMap<String, String> params) {
+    private Bundle convertParamsHashMaptoBundle(HashMap<String, String> params) {
         if (params != null && !params.isEmpty()) {
-            Bundle bundle = new Bundle(mParams);
+            Bundle bundle = new Bundle();
             copyIntParam(bundle, params, Engine.KEY_PARAM_STREAM);
             copyIntParam(bundle, params, Engine.KEY_PARAM_SESSION_ID);
             copyStringParam(bundle, params, Engine.KEY_PARAM_UTTERANCE_ID);
@@ -1852,11 +1875,85 @@
             }
 
             return bundle;
+        }
+        return null;
+    }
+
+    private Bundle getParams(Bundle params) {
+        if (params != null && !params.isEmpty()) {
+            Bundle bundle = new Bundle(mParams);
+            bundle.putAll(params);
+
+            verifyIntegerBundleParam(bundle, Engine.KEY_PARAM_STREAM);
+            verifyIntegerBundleParam(bundle, Engine.KEY_PARAM_SESSION_ID);
+            verifyStringBundleParam(bundle, Engine.KEY_PARAM_UTTERANCE_ID);
+            verifyFloatBundleParam(bundle, Engine.KEY_PARAM_VOLUME);
+            verifyFloatBundleParam(bundle, Engine.KEY_PARAM_PAN);
+
+            // Copy feature strings defined by the framework.
+            verifyBooleanBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_SYNTHESIS);
+            verifyBooleanBundleParam(bundle, Engine.KEY_FEATURE_EMBEDDED_SYNTHESIS);
+            verifyIntegerBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_TIMEOUT_MS);
+            verifyIntegerBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_RETRIES_COUNT);
+
+            return bundle;
         } else {
             return mParams;
         }
     }
 
+    private static boolean verifyIntegerBundleParam(Bundle bundle, String key) {
+        if (bundle.containsKey(key)) {
+            if (!(bundle.get(key) instanceof Integer ||
+                    bundle.get(key) instanceof Long)) {
+                bundle.remove(key);
+                Log.w(TAG, "Synthesis request paramter " + key + " containst value "
+                        + " with invalid type. Should be an Integer or a Long");
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static boolean verifyStringBundleParam(Bundle bundle, String key) {
+        if (bundle.containsKey(key)) {
+            if (!(bundle.get(key) instanceof String)) {
+                bundle.remove(key);
+                Log.w(TAG, "Synthesis request paramter " + key + " containst value "
+                        + " with invalid type. Should be a String");
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static boolean verifyBooleanBundleParam(Bundle bundle, String key) {
+        if (bundle.containsKey(key)) {
+            if (!(bundle.get(key) instanceof Boolean ||
+                    bundle.get(key) instanceof String)) {
+                bundle.remove(key);
+                Log.w(TAG, "Synthesis request paramter " + key + " containst value "
+                        + " with invalid type. Should be a Boolean or String");
+                return false;
+            }
+        }
+        return true;
+    }
+
+
+    private static boolean verifyFloatBundleParam(Bundle bundle, String key) {
+        if (bundle.containsKey(key)) {
+            if (!(bundle.get(key) instanceof Float ||
+                    bundle.get(key) instanceof Double)) {
+                bundle.remove(key);
+                Log.w(TAG, "Synthesis request paramter " + key + " containst value "
+                        + " with invalid type. Should be a Float or a Double");
+                return false;
+            }
+        }
+        return true;
+    }
+
     private void copyStringParam(Bundle bundle, HashMap<String, String> params, String key) {
         String value = params.get(key);
         if (value != null) {
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 4fea109..d00a433 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -84,7 +84,7 @@
  * the following methods:
  * <ul>
  * <li>{@link #onGetVoices()}</li>
- * <li>{@link #isValidVoiceName(String)}</li>
+ * <li>{@link #onIsValidVoiceName(String)}</li>
  * <li>{@link #onLoadVoice(String)}</li>
  * <li>{@link #onGetDefaultVoiceNameFor(String, String, String)}</li>
  * </ul>
@@ -278,7 +278,7 @@
      *
      * @return A list of voices supported.
      */
-    protected List<Voice> onGetVoices() {
+    public List<Voice> onGetVoices() {
         // Enumerate all locales and check if they are available
         ArrayList<Voice> voices = new ArrayList<Voice>();
         for (Locale locale : Locale.getAvailableLocales()) {
@@ -335,7 +335,7 @@
         }
         Locale properLocale = TtsEngines.normalizeTTSLocale(iso3Locale);
         String voiceName = properLocale.toLanguageTag();
-        if (isValidVoiceName(voiceName) == TextToSpeech.SUCCESS) {
+        if (onIsValidVoiceName(voiceName) == TextToSpeech.SUCCESS) {
             return voiceName;
         } else {
             return null;
@@ -357,7 +357,7 @@
      * @param voiceName Name of the voice.
      * @return {@link TextToSpeech#ERROR} or {@link TextToSpeech#SUCCESS}.
      */
-    protected int onLoadVoice(String voiceName) {
+    public int onLoadVoice(String voiceName) {
         Locale locale = Locale.forLanguageTag(voiceName);
         if (locale == null) {
             return TextToSpeech.ERROR;
@@ -388,7 +388,7 @@
      * @param voiceName Name of the voice.
      * @return {@link TextToSpeech#ERROR} or {@link TextToSpeech#SUCCESS}.
      */
-    protected int isValidVoiceName(String voiceName) {
+    public int onIsValidVoiceName(String voiceName) {
         Locale locale = Locale.forLanguageTag(voiceName);
         if (locale == null) {
             return TextToSpeech.ERROR;
@@ -1275,7 +1275,7 @@
             if (!checkNonNull(voiceName)) {
                 return TextToSpeech.ERROR;
             }
-            int retVal = isValidVoiceName(voiceName);
+            int retVal = onIsValidVoiceName(voiceName);
 
             if (retVal == TextToSpeech.SUCCESS) {
                 SpeechItem item = new LoadVoiceItem(caller, Binder.getCallingUid(),
diff --git a/core/java/android/speech/tts/Voice.java b/core/java/android/speech/tts/Voice.java
index a97141c..a1fa51d 100644
--- a/core/java/android/speech/tts/Voice.java
+++ b/core/java/android/speech/tts/Voice.java
@@ -162,7 +162,7 @@
     /**
      * @return Does the Voice require a network connection to work.
      */
-    public boolean getRequiresNetworkConnection() {
+    public boolean isNetworkConnectionRequired() {
         return mRequiresNetworkConnection;
     }
 
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 0d1b568..40bb6ec 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -1417,9 +1417,9 @@
                     }
                     capturePropagationValues(values);
                     if (start) {
-                        addViewValues(mStartValues, view, values);
+                        addViewValues(mStartValues, view, values, true);
                     } else {
-                        addViewValues(mEndValues, view, values);
+                        addViewValues(mEndValues, view, values, true);
                     }
                 }
             }
@@ -1460,7 +1460,7 @@
     }
 
     static void addViewValues(TransitionValuesMaps transitionValuesMaps,
-            View view, TransitionValues transitionValues) {
+            View view, TransitionValues transitionValues, boolean setTransientState) {
         transitionValuesMaps.viewValues.put(view, transitionValues);
         int id = view.getId();
         if (id >= 0) {
@@ -1489,11 +1489,15 @@
                     // Duplicate item IDs: cannot match by item ID.
                     View alreadyMatched = transitionValuesMaps.itemIdValues.get(itemId);
                     if (alreadyMatched != null) {
-                        alreadyMatched.setHasTransientState(false);
+                        if (setTransientState) {
+                            alreadyMatched.setHasTransientState(false);
+                        }
                         transitionValuesMaps.itemIdValues.put(itemId, null);
                     }
                 } else {
-                    view.setHasTransientState(true);
+                    if (setTransientState) {
+                        view.setHasTransientState(true);
+                    }
                     transitionValuesMaps.itemIdValues.put(itemId, view);
                 }
             }
@@ -1560,9 +1564,9 @@
             }
             capturePropagationValues(values);
             if (start) {
-                addViewValues(mStartValues, view, values);
+                addViewValues(mStartValues, view, values, true);
             } else {
-                addViewValues(mEndValues, view, values);
+                addViewValues(mEndValues, view, values, true);
             }
         }
         if (view instanceof ViewGroup) {
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index f6499ae..56db674 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -408,7 +408,7 @@
         for (int i = 0; i < numValues; i++) {
             View view = values.viewValues.keyAt(i);
             if (isValidTarget(view)) {
-                addViewValues(included, view, values.viewValues.valueAt(i));
+                addViewValues(included, view, values.viewValues.valueAt(i), false);
             }
         }
         return included;
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 0b02552..d648ca6 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -358,12 +358,16 @@
                     overlayView = startView;
                 } else if (startView.getParent() instanceof View) {
                     View startParent = (View) startView.getParent();
-                    if (!isValidTarget(startParent)) {
-                        if (startView.isAttachedToWindow()) {
-                            overlayView = copyViewImage(startView);
-                        } else {
-                            overlayView = startView;
-                        }
+                    VisibilityInfo parentVisibilityInfo = null;
+                    TransitionValues endParentValues = getMatchedTransitionValues(startParent,
+                            true);
+                    if (endParentValues != null) {
+                        TransitionValues startParentValues = getTransitionValues(startParent, true);
+                        parentVisibilityInfo =
+                                getVisibilityChangeInfo(startParentValues, endParentValues);
+                    }
+                    if (parentVisibilityInfo == null || !parentVisibilityInfo.visibilityChange) {
+                        overlayView = copyViewImage(startView);
                     } else if (startParent.getParent() == null) {
                         int id = startParent.getId();
                         if (id != View.NO_ID && sceneRoot.findViewById(id) != null
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5d6d998..6aa86c7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -94,7 +94,8 @@
     void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
             IRemoteCallback startedCallback, boolean scaleUp);
     void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX,
-            int startY, IRemoteCallback startedCallback, boolean scaleUp);
+            int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
+            boolean scaleUp);
     void executeAppTransition();
     void setAppStartingWindow(IBinder token, String pkg, int theme,
             in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 9dc9766..47f72a8 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -367,6 +367,10 @@
         throw new IllegalArgumentException("Unrecognized outline?");
     }
 
+    public boolean hasShadow() {
+        return nHasShadow(mNativeRenderNode);
+    }
+
     /**
      * Enables or disables clipping to the outline.
      *
@@ -861,6 +865,7 @@
             float alpha);
     private static native boolean nSetOutlineEmpty(long renderNode);
     private static native boolean nSetOutlineNone(long renderNode);
+    private static native boolean nHasShadow(long renderNode);
     private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
     private static native boolean nSetRevealClip(long renderNode,
             boolean shouldClip, float x, float y, float radius);
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index fa4a13a..debf45d 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -453,6 +453,12 @@
         throw new IllegalStateException("Cannot clone this animator");
     }
 
+    @Override
+    public void setAllowRunningAsynchronously(boolean mayRunAsync) {
+        checkMutable();
+        nSetAllowRunningAsync(mNativePtr.get(), mayRunAsync);
+    }
+
     private static native long nCreateAnimator(int property, float finalValue);
     private static native long nCreateCanvasPropertyFloatAnimator(
             long canvasProperty, float finalValue);
@@ -466,6 +472,7 @@
     private static native long nGetDuration(long nativePtr);
     private static native void nSetStartDelay(long nativePtr, long startDelay);
     private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
+    private static native void nSetAllowRunningAsync(long animPtr, boolean mayRunAsync);
 
     private static native void nStart(long animPtr, RenderNodeAnimator finishListener);
     private static native void nEnd(long animPtr);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1e12ddc..82c5425 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10356,6 +10356,7 @@
      *
      * @return true if the content in this view might overlap, false otherwise.
      */
+    @ViewDebug.ExportedProperty(category = "drawing")
     public boolean hasOverlappingRendering() {
         return true;
     }
@@ -11058,6 +11059,17 @@
         invalidateViewProperty(false, false);
     }
 
+    /**
+     * HierarchyViewer only
+     *
+     * @hide
+     */
+    @ViewDebug.ExportedProperty(category = "drawing")
+    public boolean hasShadow() {
+        return mRenderNode.hasShadow();
+    }
+
+
     /** @hide */
     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
         mRenderNode.setRevealClip(shouldClip, x, y, radius);
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 6c66eb0..a94f973 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -26,6 +26,7 @@
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.TypedValue;
 
 import java.io.BufferedOutputStream;
 import java.io.BufferedWriter;
@@ -315,6 +316,7 @@
 
     private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE";
     private static final String REMOTE_COMMAND_DUMP = "DUMP";
+    private static final String REMOTE_COMMAND_DUMP_THEME = "DUMP_THEME";
     private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE";
     private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT";
     private static final String REMOTE_PROFILE = "PROFILE";
@@ -430,6 +432,8 @@
 
         if (REMOTE_COMMAND_DUMP.equalsIgnoreCase(command)) {
             dump(view, false, true, clientStream);
+        } else if (REMOTE_COMMAND_DUMP_THEME.equalsIgnoreCase(command)) {
+            dumpTheme(view, clientStream);
         } else if (REMOTE_COMMAND_CAPTURE_LAYERS.equalsIgnoreCase(command)) {
             captureLayers(view, new DataOutputStream(clientStream));
         } else {
@@ -820,6 +824,64 @@
         }
     }
 
+    /**
+     * Dumps the theme attributes from the given View.
+     * @hide
+     */
+    public static void dumpTheme(View view, OutputStream clientStream) throws IOException {
+        BufferedWriter out = null;
+        try {
+            out = new BufferedWriter(new OutputStreamWriter(clientStream, "utf-8"), 32 * 1024);
+            String[] attributes = getStyleAttributesDump(view.getContext().getResources(),
+                    view.getContext().getTheme());
+            if (attributes != null) {
+                for (int i = 0; i < attributes.length; i += 2) {
+                    if (attributes[i] != null) {
+                        out.write(attributes[i] + "\n");
+                        out.write(attributes[i + 1] + "\n");
+                    }
+                }
+            }
+            out.write("DONE.");
+            out.newLine();
+        } catch (Exception e) {
+            android.util.Log.w("View", "Problem dumping View Theme:", e);
+        } finally {
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+
+    /**
+     * Gets the style attributes from the {@link Resources.Theme}. For debugging only.
+     *
+     * @param resources Resources to resolve attributes from.
+     * @param theme Theme to dump.
+     * @return a String array containing pairs of adjacent Theme attribute data: name followed by
+     * its value.
+     *
+     * @hide
+     */
+    private static String[] getStyleAttributesDump(Resources resources, Resources.Theme theme) {
+        TypedValue outValue = new TypedValue();
+        String nullString = "null";
+        int i = 0;
+        int[] attributes = theme.getAllAttributes();
+        String[] data = new String[attributes.length * 2];
+        for (int attributeId : attributes) {
+            try {
+                data[i] = resources.getResourceName(attributeId);
+                data[i + 1] = theme.resolveAttribute(attributeId, outValue, true) ?
+                        outValue.coerceToString().toString() :  nullString;
+                i += 2;
+            } catch (Resources.NotFoundException e) {
+                // ignore resources we can't resolve
+            }
+        }
+        return data;
+    }
+
     private static View findView(ViewGroup group, String className, int hashCode) {
         if (isRequestedView(group, className, hashCode)) {
             return group;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index b4f1910..4e1db90 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3407,6 +3407,7 @@
      * @return True if the group's children will be clipped to their bounds,
      * false otherwise.
      */
+    @ViewDebug.ExportedProperty(category = "drawing")
     public boolean getClipChildren() {
         return ((mGroupFlags & FLAG_CLIP_CHILDREN) != 0);
     }
@@ -3455,6 +3456,7 @@
      *
      * @attr ref android.R.styleable#ViewGroup_clipToPadding
      */
+    @ViewDebug.ExportedProperty(category = "drawing")
     public boolean getClipToPadding() {
         return hasBooleanFlag(FLAG_CLIP_TO_PADDING);
     }
@@ -5828,6 +5830,28 @@
     }
 
     @Override
+    public void drawableHotspotChanged(float x, float y) {
+        super.drawableHotspotChanged(x, y);
+
+        if ((mGroupFlags & FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE) != 0) {
+            if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0) {
+                throw new IllegalStateException("addStateFromChildren cannot be enabled if a"
+                        + " child has duplicateParentState set to true");
+            }
+
+            final View[] children = mChildren;
+            final int count = mChildrenCount;
+
+            for (int i = 0; i < count; i++) {
+                final View child = children[i];
+                if ((child.mViewFlags & DUPLICATE_PARENT_STATE) != 0) {
+                    child.drawableHotspotChanged(x, y);
+                }
+            }
+        }
+    }
+
+    @Override
     protected int[] onCreateDrawableState(int extraSpace) {
         if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) == 0) {
             return super.onCreateDrawableState(extraSpace);
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index b7b12a8..2ed125d 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -770,7 +770,8 @@
     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
 
     /**
-     * Called from the input reader thread before a motion is enqueued when the screen is off.
+     * Called from the input reader thread before a motion is enqueued when the device is in a
+     * non-interactive state.
      *
      * <p>There are some actions that need to be handled here because they
      * affect the power state of the device, for example, waking on motions.
@@ -780,7 +781,7 @@
      *
      * @return Actions flags: may be {@link #ACTION_PASS_TO_USER}.
      */
-    public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags);
+    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
 
     /**
      * Called from the input dispatcher thread before a key is dispatched to a window.
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java
index fe0f5b9..600fffe 100644
--- a/core/java/android/view/inputmethod/CursorAnchorInfo.java
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java
@@ -35,9 +35,21 @@
  * actually inserted.</p>
  */
 public final class CursorAnchorInfo implements Parcelable {
+    /**
+     * The index of the first character of the selected text (inclusive). {@code -1} when there is
+     * no text selection.
+     */
     private final int mSelectionStart;
+    /**
+     * The index of the first character of the selected text (exclusive). {@code -1} when there is
+     * no text selection.
+     */
     private final int mSelectionEnd;
 
+    /**
+     * The index of the first character of the composing text (inclusive). {@code -1} when there is
+     * no composing text.
+     */
     private final int mComposingTextStart;
     /**
      * The text, tracked as a composing region.
@@ -82,7 +94,7 @@
      * Java chars, in the local coordinates that will be transformed with the transformation matrix
      * when rendered on the screen.
      */
-    private final SparseRectFArray mCharacterRects;
+    private final SparseRectFArray mCharacterBoundsArray;
 
     /**
      * Transformation matrix that is applied to any positional information of this class to
@@ -91,18 +103,24 @@
     private final Matrix mMatrix;
 
     /**
-     * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the
+     * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
      * insertion marker or character bounds have at least one visible region.
      */
     public static final int FLAG_HAS_VISIBLE_REGION = 0x01;
 
     /**
-     * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the
+     * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
      * insertion marker or character bounds have at least one invisible (clipped) region.
      */
     public static final int FLAG_HAS_INVISIBLE_REGION = 0x02;
 
     /**
+     * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
+     * insertion marker or character bounds is placed at right-to-left (RTL) character.
+     */
+    public static final int FLAG_IS_RTL = 0x04;
+
+    /**
      * @removed
      */
     public static final int CHARACTER_RECT_TYPE_MASK = 0x0f;
@@ -144,7 +162,7 @@
         mInsertionMarkerTop = source.readFloat();
         mInsertionMarkerBaseline = source.readFloat();
         mInsertionMarkerBottom = source.readFloat();
-        mCharacterRects = source.readParcelable(SparseRectFArray.class.getClassLoader());
+        mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader());
         mMatrix = new Matrix();
         mMatrix.setValues(source.createFloatArray());
     }
@@ -166,7 +184,7 @@
         dest.writeFloat(mInsertionMarkerTop);
         dest.writeFloat(mInsertionMarkerBaseline);
         dest.writeFloat(mInsertionMarkerBottom);
-        dest.writeParcelable(mCharacterRects, flags);
+        dest.writeParcelable(mCharacterBoundsArray, flags);
         final float[] matrixArray = new float[9];
         mMatrix.getValues(matrixArray);
         dest.writeFloatArray(matrixArray);
@@ -174,7 +192,6 @@
 
     @Override
     public int hashCode(){
-        // TODO: Improve the hash function.
         final float floatHash = mInsertionMarkerHorizontal + mInsertionMarkerTop
                 + mInsertionMarkerBaseline + mInsertionMarkerBottom;
         int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash);
@@ -185,7 +202,7 @@
         hash *= 31;
         hash += Objects.hashCode(mComposingText);
         hash *= 31;
-        hash += Objects.hashCode(mCharacterRects);
+        hash += Objects.hashCode(mCharacterBoundsArray);
         hash *= 31;
         hash += Objects.hashCode(mMatrix);
         return hash;
@@ -231,7 +248,7 @@
                 || !areSameFloatImpl(mInsertionMarkerBottom, that.mInsertionMarkerBottom)) {
             return false;
         }
-        if (!Objects.equals(mCharacterRects, that.mCharacterRects)) {
+        if (!Objects.equals(mCharacterBoundsArray, that.mCharacterBoundsArray)) {
             return false;
         }
         if (!Objects.equals(mMatrix, that.mMatrix)) {
@@ -250,7 +267,7 @@
                 + " mInsertionMarkerTop=" + mInsertionMarkerTop
                 + " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
                 + " mInsertionMarkerBottom=" + mInsertionMarkerBottom
-                + " mCharacterRects=" + Objects.toString(mCharacterRects)
+                + " mCharacterBoundsArray=" + Objects.toString(mCharacterBoundsArray)
                 + " mMatrix=" + Objects.toString(mMatrix)
                 + "}";
     }
@@ -259,6 +276,19 @@
      * Builder for {@link CursorAnchorInfo}. This class is not designed to be thread-safe.
      */
     public static final class Builder {
+        private int mSelectionStart = -1;
+        private int mSelectionEnd = -1;
+        private int mComposingTextStart = -1;
+        private CharSequence mComposingText = null;
+        private float mInsertionMarkerHorizontal = Float.NaN;
+        private float mInsertionMarkerTop = Float.NaN;
+        private float mInsertionMarkerBaseline = Float.NaN;
+        private float mInsertionMarkerBottom = Float.NaN;
+        private int mInsertionMarkerFlags = 0;
+        private SparseRectFArrayBuilder mCharacterBoundsArrayBuilder = null;
+        private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX);
+        private boolean mMatrixInitialized = false;
+
         /**
          * Sets the text range of the selection. Calling this can be skipped if there is no
          * selection.
@@ -268,8 +298,6 @@
             mSelectionEnd = newEnd;
             return this;
         }
-        private int mSelectionStart = -1;
-        private int mSelectionEnd = -1;
 
         /**
          * Sets the text range of the composing text. Calling this can be skipped if there is
@@ -288,8 +316,6 @@
             }
             return this;
         }
-        private int mComposingTextStart = -1;
-        private CharSequence mComposingText = null;
 
         /**
          * @removed
@@ -335,11 +361,33 @@
             mInsertionMarkerFlags = flags;
             return this;
         }
-        private float mInsertionMarkerHorizontal = Float.NaN;
-        private float mInsertionMarkerTop = Float.NaN;
-        private float mInsertionMarkerBaseline = Float.NaN;
-        private float mInsertionMarkerBottom = Float.NaN;
-        private int mInsertionMarkerFlags = 0;
+
+        /**
+         * Adds the bounding box of the character specified with the index.
+         *
+         * @param index index of the character in Java chars units. Must be specified in
+         * ascending order across successive calls.
+         * @param left x coordinate of the left edge of the character in local coordinates.
+         * @param top y coordinate of the top edge of the character in local coordinates.
+         * @param right x coordinate of the right edge of the character in local coordinates.
+         * @param bottom y coordinate of the bottom edge of the character in local coordinates.
+         * @param flags flags for this character bounds. See {@link #FLAG_HAS_VISIBLE_REGION},
+         * {@link #FLAG_HAS_INVISIBLE_REGION} and {@link #FLAG_IS_RTL}. These flags must be
+         * specified when necessary.
+         * @throws IllegalArgumentException If the index is a negative value, or not greater than
+         * all of the previously called indices.
+         */
+        public Builder addCharacterBounds(final int index, final float left, final float top,
+                final float right, final float bottom, final int flags) {
+            if (index < 0) {
+                throw new IllegalArgumentException("index must not be a negative integer.");
+            }
+            if (mCharacterBoundsArrayBuilder == null) {
+                mCharacterBoundsArrayBuilder = new SparseRectFArrayBuilder();
+            }
+            mCharacterBoundsArrayBuilder.append(index, left, top, right, bottom, flags);
+            return this;
+        }
 
         /**
          * Adds the bounding box of the character specified with the index.
@@ -358,21 +406,25 @@
          * example.
          * @throws IllegalArgumentException If the index is a negative value, or not greater than
          * all of the previously called indices.
+         * @removed
          */
         public Builder addCharacterRect(final int index, final float leadingEdgeX,
                 final float leadingEdgeY, final float trailingEdgeX, final float trailingEdgeY,
                 final int flags) {
-            if (index < 0) {
-                throw new IllegalArgumentException("index must not be a negative integer.");
+            final int newFlags;
+            final float left;
+            final float right;
+            if (leadingEdgeX <= trailingEdgeX) {
+                newFlags = flags;
+                left = leadingEdgeX;
+                right = trailingEdgeX;
+            } else {
+                newFlags = flags | FLAG_IS_RTL;
+                left = trailingEdgeX;
+                right = leadingEdgeX;
             }
-            if (mCharacterRectBuilder == null) {
-                mCharacterRectBuilder = new SparseRectFArrayBuilder();
-            }
-            mCharacterRectBuilder.append(index, leadingEdgeX, leadingEdgeY, trailingEdgeX,
-                    trailingEdgeY, flags);
-            return this;
+            return addCharacterBounds(index, left, leadingEdgeY, right, trailingEdgeY, newFlags);
         }
-        private SparseRectFArrayBuilder mCharacterRectBuilder = null;
 
         /**
          * Sets the matrix that transforms local coordinates into screen coordinates.
@@ -384,8 +436,6 @@
             mMatrixInitialized = true;
             return this;
         }
-        private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX);
-        private boolean mMatrixInitialized = false;
 
         /**
          * @return {@link CursorAnchorInfo} using parameters in this {@link Builder}.
@@ -394,13 +444,15 @@
          */
         public CursorAnchorInfo build() {
             if (!mMatrixInitialized) {
-                // Coordinate transformation matrix is mandatory when positional parameters are
-                // specified.
-                if ((mCharacterRectBuilder != null && !mCharacterRectBuilder.isEmpty()) ||
-                        !Float.isNaN(mInsertionMarkerHorizontal) ||
-                        !Float.isNaN(mInsertionMarkerTop) ||
-                        !Float.isNaN(mInsertionMarkerBaseline) ||
-                        !Float.isNaN(mInsertionMarkerBottom)) {
+                // Coordinate transformation matrix is mandatory when at least one positional
+                // parameter is specified.
+                final boolean hasCharacterBounds = (mCharacterBoundsArrayBuilder != null
+                        && !mCharacterBoundsArrayBuilder.isEmpty());
+                if (hasCharacterBounds
+                        || !Float.isNaN(mInsertionMarkerHorizontal)
+                        || !Float.isNaN(mInsertionMarkerTop)
+                        || !Float.isNaN(mInsertionMarkerBaseline)
+                        || !Float.isNaN(mInsertionMarkerBottom)) {
                     throw new IllegalArgumentException("Coordinate transformation matrix is " +
                             "required when positional parameters are specified.");
                 }
@@ -424,8 +476,8 @@
             mInsertionMarkerBottom = Float.NaN;
             mMatrix.set(Matrix.IDENTITY_MATRIX);
             mMatrixInitialized = false;
-            if (mCharacterRectBuilder != null) {
-                mCharacterRectBuilder.reset();
+            if (mCharacterBoundsArrayBuilder != null) {
+                mCharacterBoundsArrayBuilder.reset();
             }
         }
     }
@@ -440,8 +492,8 @@
         mInsertionMarkerTop = builder.mInsertionMarkerTop;
         mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline;
         mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
-        mCharacterRects = builder.mCharacterRectBuilder != null ?
-                builder.mCharacterRectBuilder.build() : null;
+        mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null ?
+                builder.mCharacterBoundsArrayBuilder.build() : null;
         mMatrix = new Matrix(builder.mMatrix);
     }
 
@@ -539,6 +591,19 @@
     /**
      * Returns a new instance of {@link RectF} that indicates the location of the character
      * specified with the index.
+     * @param index index of the character in a Java chars.
+     * @return the character bounds in local coordinates as a new instance of {@link RectF}.
+     */
+    public RectF getCharacterBounds(final int index) {
+        if (mCharacterBoundsArray == null) {
+            return null;
+        }
+        return mCharacterBoundsArray.get(index);
+    }
+
+    /**
+     * Returns a new instance of {@link RectF} that indicates the location of the character
+     * specified with the index.
      * <p>
      * Note that coordinates are not necessarily contiguous or even monotonous, especially when
      * RTL text and LTR text are mixed.
@@ -549,28 +614,32 @@
      * the location. Note that the {@code left} field can be greater than the {@code right} field
      * if the character is in RTL text. Returns {@code null} if no location information is
      * available.
+     * @removed
      */
-    // TODO: Prepare a document about the expected behavior for surrogate pairs, combining
-    // characters, and non-graphical chars.
     public RectF getCharacterRect(final int index) {
-        if (mCharacterRects == null) {
-            return null;
+        return getCharacterBounds(index);
+    }
+
+    /**
+     * Returns the flags associated with the character bounds specified with the index.
+     * @param index index of the character in a Java chars.
+     * @return {@code 0} if no flag is specified.
+     */
+    public int getCharacterBoundsFlags(final int index) {
+        if (mCharacterBoundsArray == null) {
+            return 0;
         }
-        return mCharacterRects.get(index);
+        return mCharacterBoundsArray.getFlags(index, 0);
     }
 
     /**
      * Returns the flags associated with the character rect specified with the index.
      * @param index index of the character in a Java chars.
      * @return {@code 0} if no flag is specified.
+     * @removed
      */
-    // TODO: Prepare a document about the expected behavior for surrogate pairs, combining
-    // characters, and non-graphical chars.
     public int getCharacterRectFlags(final int index) {
-        if (mCharacterRects == null) {
-            return 0;
-        }
-        return mCharacterRects.getFlags(index, 0);
+        return getCharacterBoundsFlags(index);
     }
 
     /**
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 2729bd0..d77f0b2 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -125,6 +125,7 @@
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker,
                 defStyleAttr, defStyleRes);
         final int mode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER);
+        final int firstDayOfWeek = a.getInt(R.styleable.DatePicker_firstDayOfWeek, 0);
         a.recycle();
 
         switch (mode) {
@@ -136,6 +137,10 @@
                 mDelegate = createSpinnerUIDelegate(context, attrs, defStyleAttr, defStyleRes);
                 break;
         }
+
+        if (firstDayOfWeek != 0) {
+            setFirstDayOfWeek(firstDayOfWeek);
+        }
     }
 
     private DatePickerDelegate createSpinnerUIDelegate(Context context, AttributeSet attrs,
@@ -300,6 +305,47 @@
     }
 
     /**
+     * Sets the first day of week.
+     *
+     * @param firstDayOfWeek The first day of the week conforming to the
+     *            {@link CalendarView} APIs.
+     * @see Calendar#SUNDAY
+     * @see Calendar#MONDAY
+     * @see Calendar#TUESDAY
+     * @see Calendar#WEDNESDAY
+     * @see Calendar#THURSDAY
+     * @see Calendar#FRIDAY
+     * @see Calendar#SATURDAY
+     *
+     * @attr ref android.R.styleable#DatePicker_firstDayOfWeek
+     */
+    public void setFirstDayOfWeek(int firstDayOfWeek) {
+        if (firstDayOfWeek < Calendar.SUNDAY || firstDayOfWeek > Calendar.SATURDAY) {
+            throw new IllegalArgumentException("firstDayOfWeek must be between 1 and 7");
+        }
+        mDelegate.setFirstDayOfWeek(firstDayOfWeek);
+    }
+
+    /**
+     * Gets the first day of week.
+     *
+     * @return The first day of the week conforming to the {@link CalendarView}
+     *         APIs.
+     * @see Calendar#SUNDAY
+     * @see Calendar#MONDAY
+     * @see Calendar#TUESDAY
+     * @see Calendar#WEDNESDAY
+     * @see Calendar#THURSDAY
+     * @see Calendar#FRIDAY
+     * @see Calendar#SATURDAY
+     *
+     * @attr ref android.R.styleable#DatePicker_firstDayOfWeek
+     */
+    public int getFirstDayOfWeek() {
+        return mDelegate.getFirstDayOfWeek();
+    }
+
+    /**
      * Gets whether the {@link CalendarView} is shown.
      *
      * @return True if the calendar view is shown.
@@ -315,7 +361,7 @@
      * @return The calendar view.
      * @see #getCalendarViewShown()
      */
-    public CalendarView getCalendarView () {
+    public CalendarView getCalendarView() {
         return mDelegate.getCalendarView();
     }
 
@@ -382,6 +428,9 @@
         int getMonth();
         int getDayOfMonth();
 
+        void setFirstDayOfWeek(int firstDayOfWeek);
+        int getFirstDayOfWeek();
+
         void setMinDate(long minDate);
         Calendar getMinDate();
 
@@ -699,6 +748,16 @@
         }
 
         @Override
+        public void setFirstDayOfWeek(int firstDayOfWeek) {
+            mCalendarView.setFirstDayOfWeek(firstDayOfWeek);
+        }
+
+        @Override
+        public int getFirstDayOfWeek() {
+            return mCalendarView.getFirstDayOfWeek();
+        }
+
+        @Override
         public void setMinDate(long minDate) {
             mTempDate.setTimeInMillis(minDate);
             if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index eed49bf..b962962 100644
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -49,6 +49,7 @@
  */
 class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate implements
         View.OnClickListener, DatePickerController {
+    private static final int USE_LOCALE = 0;
 
     private static final int UNINITIALIZED = -1;
     private static final int MONTH_AND_DAY_VIEW = 0;
@@ -99,6 +100,8 @@
     private Calendar mMinDate;
     private Calendar mMaxDate;
 
+    private int mFirstDayOfWeek = USE_LOCALE;
+
     private HashSet<OnDateChangedListener> mListeners = new HashSet<OnDateChangedListener>();
 
     public DatePickerCalendarDelegate(DatePicker delegator, Context context, AttributeSet attrs,
@@ -438,7 +441,15 @@
     }
 
     @Override
+    public void setFirstDayOfWeek(int firstDayOfWeek) {
+        mFirstDayOfWeek = firstDayOfWeek;
+    }
+
+    @Override
     public int getFirstDayOfWeek() {
+        if (mFirstDayOfWeek != USE_LOCALE) {
+            return mFirstDayOfWeek;
+        }
         return mCurrentDate.getFirstDayOfWeek();
     }
 
diff --git a/core/java/android/widget/DatePickerController.java b/core/java/android/widget/DatePickerController.java
index 6a074da..059709d 100644
--- a/core/java/android/widget/DatePickerController.java
+++ b/core/java/android/widget/DatePickerController.java
@@ -35,6 +35,7 @@
 
     Calendar getSelectedDay();
 
+    void setFirstDayOfWeek(int firstDayOfWeek);
     int getFirstDayOfWeek();
 
     int getMinYear();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 22138d0..3f168e8 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3060,47 +3060,69 @@
                     final CharSequence composingText = text.subSequence(composingTextStart,
                             composingTextEnd);
                     builder.setComposingText(composingTextStart, composingText);
-                }
-                // TODO: Optimize this loop by caching the result.
-                for (int offset = composingTextStart; offset < composingTextEnd; offset++) {
-                    if (offset < 0) {
-                        continue;
+
+                    final int minLine = layout.getLineForOffset(composingTextStart);
+                    final int maxLine = layout.getLineForOffset(composingTextEnd - 1);
+                    for (int line = minLine; line <= maxLine; ++line) {
+                        final int lineStart = layout.getLineStart(line);
+                        final int lineEnd = layout.getLineEnd(line);
+                        final int offsetStart = Math.max(lineStart, composingTextStart);
+                        final int offsetEnd = Math.min(lineEnd, composingTextEnd);
+                        final boolean ltrLine =
+                                layout.getParagraphDirection(line) == Layout.DIR_LEFT_TO_RIGHT;
+                        final float[] widths = new float[offsetEnd - offsetStart];
+                        layout.getPaint().getTextWidths(text, offsetStart, offsetEnd, widths);
+                        final float top = layout.getLineTop(line);
+                        final float bottom = layout.getLineBottom(line);
+                        for (int offset = offsetStart; offset < offsetEnd; ++offset) {
+                            final float charWidth = widths[offset - offsetStart];
+                            final boolean isRtl = layout.isRtlCharAt(offset);
+                            final float primary = layout.getPrimaryHorizontal(offset);
+                            final float secondary = layout.getSecondaryHorizontal(offset);
+                            // TODO: This doesn't work perfectly for text with custom styles and
+                            // TAB chars.
+                            final float left;
+                            final float right;
+                            if (ltrLine) {
+                                if (isRtl) {
+                                    left = secondary - charWidth;
+                                    right = secondary;
+                                } else {
+                                    left = primary;
+                                    right = primary + charWidth;
+                                }
+                            } else {
+                                if (!isRtl) {
+                                    left = secondary;
+                                    right = secondary + charWidth;
+                                } else {
+                                    left = primary - charWidth;
+                                    right = primary;
+                                }
+                            }
+                            // TODO: Check top-right and bottom-left as well.
+                            final float localLeft = left + viewportToContentHorizontalOffset;
+                            final float localRight = right + viewportToContentHorizontalOffset;
+                            final float localTop = top + viewportToContentVerticalOffset;
+                            final float localBottom = bottom + viewportToContentVerticalOffset;
+                            final boolean isTopLeftVisible = isPositionVisible(localLeft, localTop);
+                            final boolean isBottomRightVisible =
+                                    isPositionVisible(localRight, localBottom);
+                            int characterBoundsFlags = 0;
+                            if (isTopLeftVisible || isBottomRightVisible) {
+                                characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+                            }
+                            if (!isTopLeftVisible || !isTopLeftVisible) {
+                                characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+                            }
+                            if (isRtl) {
+                                characterBoundsFlags |= CursorAnchorInfo.FLAG_IS_RTL;
+                            }
+                            // Here offset is the index in Java chars.
+                            builder.addCharacterBounds(offset, localLeft, localTop, localRight,
+                                    localBottom, characterBoundsFlags);
+                        }
                     }
-                    final boolean isRtl = layout.isRtlCharAt(offset);
-                    final int line = layout.getLineForOffset(offset);
-                    final int nextCharIndex = offset + 1;
-                    final float localLeadingEdgeX = layout.getPrimaryHorizontal(offset);
-                    final float localTrailingEdgeX;
-                    if (nextCharIndex != layout.getLineEnd(line)) {
-                        localTrailingEdgeX = layout.getPrimaryHorizontal(nextCharIndex);
-                    } else if (isRtl) {
-                        localTrailingEdgeX = layout.getLineLeft(line);
-                    } else {
-                        localTrailingEdgeX = layout.getLineRight(line);
-                    }
-                    final float leadingEdgeX = localLeadingEdgeX
-                            + viewportToContentHorizontalOffset;
-                    final float trailingEdgeX = localTrailingEdgeX
-                            + viewportToContentHorizontalOffset;
-                    final float top = layout.getLineTop(line) + viewportToContentVerticalOffset;
-                    final float bottom = layout.getLineBottom(line)
-                            + viewportToContentVerticalOffset;
-                    // TODO: Check right-top and left-bottom as well.
-                    final boolean isLeadingEdgeTopVisible = isPositionVisible(leadingEdgeX, top);
-                    final boolean isTrailingEdgeBottomVisible =
-                            isPositionVisible(trailingEdgeX, bottom);
-                    int characterRectFlags = 0;
-                    if (isLeadingEdgeTopVisible || isTrailingEdgeBottomVisible) {
-                        characterRectFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
-                    }
-                    if (!isLeadingEdgeTopVisible || !isTrailingEdgeBottomVisible) {
-                        characterRectFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
-                    }
-                    // Here offset is the index in Java chars.
-                    // TODO: We must have a well-defined specification. For example, how
-                    // surrogate pairs and composition letters are handled must be documented.
-                    builder.addCharacterRect(offset, leadingEdgeX, top, trailingEdgeX, bottom,
-                            characterRectFlags);
                 }
             }
 
@@ -3127,6 +3149,9 @@
                 if (!isTopVisible || !isBottomVisible) {
                     insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
                 }
+                if (layout.isRtlCharAt(offset)) {
+                    insertionMarkerFlags |= CursorAnchorInfo.FLAG_IS_RTL;
+                }
                 builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop,
                         insertionMarkerBaseline, insertionMarkerBottom, insertionMarkerFlags);
             }
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index c17f4ee..7bdb4be 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -390,7 +390,10 @@
         if (!emulated && (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL)) {
             final File target = new UserEnvironment(UserHandle.USER_OWNER)
                     .getExternalStorageDirectory();
-            fitsOnExternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
+            // External is only an option when size is known
+            if (sizeBytes > 0) {
+                fitsOnExternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
+            }
         }
 
         if (prefer == RECOMMEND_INSTALL_INTERNAL) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 69cdbff..45a9dde 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -94,7 +94,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 113 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 114 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -385,10 +385,9 @@
 
     String mLastWakeupReason = null;
     long mLastWakeupUptimeMs = 0;
-    private final HashMap<String, LongSamplingCounter> mWakeupReasonStats =
-            new HashMap<String, LongSamplingCounter>();
+    private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
 
-    public Map<String, ? extends LongCounter> getWakeupReasonStats() {
+    public Map<String, ? extends Timer> getWakeupReasonStats() {
         return mWakeupReasonStats;
     }
 
@@ -1131,6 +1130,10 @@
             mCurrentReportedCount = count;
         }
 
+        public void addCurrentReportedCount(int delta) {
+            updateCurrentReportedCount(mCurrentReportedCount + delta);
+        }
+
         public void updateCurrentReportedTotalTime(long totalTime) {
             if (mTimeBaseRunning && mUnpluggedReportedTotalTime == 0) {
                 // Updating the reported value for the first time.
@@ -1141,6 +1144,10 @@
             mCurrentReportedTotalTime = totalTime;
         }
 
+        public void addCurrentReportedTotalTime(long delta) {
+            updateCurrentReportedTotalTime(mCurrentReportedTotalTime + delta);
+        }
+
         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
             if (mTrackingReportedValues) {
@@ -1688,13 +1695,13 @@
      * Get the wakeup reason counter, and create a new one if one
      * doesn't already exist.
      */
-    public LongSamplingCounter getWakeupReasonCounterLocked(String name) {
-        LongSamplingCounter counter = mWakeupReasonStats.get(name);
-        if (counter == null) {
-            counter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
-            mWakeupReasonStats.put(name, counter);
+    public SamplingTimer getWakeupReasonTimerLocked(String name) {
+        SamplingTimer timer = mWakeupReasonStats.get(name);
+        if (timer == null) {
+            timer = new SamplingTimer(mOnBatteryTimeBase, true);
+            mWakeupReasonStats.put(name, timer);
         }
-        return counter;
+        return timer;
     }
 
     private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
@@ -2753,8 +2760,9 @@
     void aggregateLastWakeupUptimeLocked(long uptimeMs) {
         if (mLastWakeupReason != null) {
             long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
-            LongSamplingCounter timer = getWakeupReasonCounterLocked(mLastWakeupReason);
-            timer.addCountLocked(deltaUptime);
+            SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
+            timer.addCurrentReportedCount(1);
+            timer.addCurrentReportedTotalTime(deltaUptime * 1000); // time is in microseconds
             mLastWakeupReason = null;
         }
     }
@@ -2762,7 +2770,7 @@
     public void noteWakeupReasonLocked(String reason) {
         final long elapsedRealtime = SystemClock.elapsedRealtime();
         final long uptime = SystemClock.uptimeMillis();
-        if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason reason \"" + reason +"\": "
+        if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
                 + Integer.toHexString(mHistoryCur.states));
         aggregateLastWakeupUptimeLocked(uptime);
         mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
@@ -6193,7 +6201,7 @@
         }
 
         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
-            StopwatchTimer t = mJobStats.stopObject(name);
+            StopwatchTimer t = mJobStats.startObject(name);
             if (t != null) {
                 t.startRunningLocked(elapsedRealtimeMs);
             }
@@ -6636,8 +6644,8 @@
         }
 
         if (mWakeupReasonStats.size() > 0) {
-            for (LongSamplingCounter timer : mWakeupReasonStats.values()) {
-                mOnBatteryScreenOffTimeBase.remove(timer);
+            for (SamplingTimer timer : mWakeupReasonStats.values()) {
+                mOnBatteryTimeBase.remove(timer);
             }
             mWakeupReasonStats.clear();
         }
@@ -7848,7 +7856,7 @@
         for (int iwr = 0; iwr < NWR; iwr++) {
             if (in.readInt() != 0) {
                 String reasonName = in.readString();
-                getWakeupReasonCounterLocked(reasonName).readSummaryFromParcelLocked(in);
+                getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
             }
         }
 
@@ -8122,12 +8130,12 @@
         }
 
         out.writeInt(mWakeupReasonStats.size());
-        for (Map.Entry<String, LongSamplingCounter> ent : mWakeupReasonStats.entrySet()) {
-            LongSamplingCounter counter = ent.getValue();
-            if (counter != null) {
+        for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
+            SamplingTimer timer = ent.getValue();
+            if (timer != null) {
                 out.writeInt(1);
                 out.writeString(ent.getKey());
-                counter.writeSummaryFromParcelLocked(out);
+                timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
             } else {
                 out.writeInt(0);
             }
@@ -8438,7 +8446,7 @@
         for (int ikw = 0; ikw < NKW; ikw++) {
             if (in.readInt() != 0) {
                 String wakelockName = in.readString();
-                SamplingTimer kwlt = new SamplingTimer(mOnBatteryTimeBase, in);
+                SamplingTimer kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, in);
                 mKernelWakelockStats.put(wakelockName, kwlt);
             }
         }
@@ -8448,9 +8456,8 @@
         for (int iwr = 0; iwr < NWR; iwr++) {
             if (in.readInt() != 0) {
                 String reasonName = in.readString();
-                LongSamplingCounter counter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase,
-                        in);
-                mWakeupReasonStats.put(reasonName, counter);
+                SamplingTimer timer = new SamplingTimer(mOnBatteryTimeBase, in);
+                mWakeupReasonStats.put(reasonName, timer);
             }
         }
 
@@ -8585,12 +8592,12 @@
                 }
             }
             out.writeInt(mWakeupReasonStats.size());
-            for (Map.Entry<String, LongSamplingCounter> ent : mWakeupReasonStats.entrySet()) {
-                LongSamplingCounter counter = ent.getValue();
-                if (counter != null) {
+            for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
+                SamplingTimer timer = ent.getValue();
+                if (timer != null) {
                     out.writeInt(1);
                     out.writeString(ent.getKey());
-                    counter.writeToParcel(out);
+                    timer.writeToParcel(out, uSecRealtime);
                 } else {
                     out.writeInt(0);
                 }
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 7db70ba..45d790b 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -1440,6 +1440,16 @@
         return Boolean.parseBoolean(value);
     }
 
+    public static boolean readBooleanAttribute(XmlPullParser in, String name,
+            boolean defaultValue) {
+        final String value = in.getAttributeValue(null, name);
+        if (value == null) {
+            return defaultValue;
+        } else {
+            return Boolean.parseBoolean(value);
+        }
+    }
+
     public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value)
             throws IOException {
         out.attribute(null, name, Boolean.toString(value));
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index f0d7a35..7b33bc2 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -211,7 +211,7 @@
     }
 
     jobject jAudioFormat = NULL;
-    if (event->trigger_in_data) {
+    if (event->trigger_in_data || event->capture_available) {
         jAudioFormat = env->NewObject(gAudioFormatClass,
                                     gAudioFormatCstor,
                                     audioFormatFromNative(event->audio_config.format),
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 5faf03d..396f3ec 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1888,6 +1888,37 @@
     return array;
 }
 
+static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
+                                                                 jint styleId)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
+    const ResTable& res(am->getResources());
+
+    const ResTable::bag_entry* startOfBag;
+    const ssize_t N = res.lockBag(styleId, &startOfBag);
+    if (N < 0) {
+        return NULL;
+    }
+
+    jintArray array = env->NewIntArray(N);
+    if (array == NULL) {
+        res.unlockBag(startOfBag);
+        return NULL;
+    }
+
+    Res_value value;
+    const ResTable::bag_entry* bag = startOfBag;
+    for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
+        int resourceId = bag->map.name.ident;
+        env->SetIntArrayRegion(array, i, 1, &resourceId);
+    }
+    res.unlockBag(startOfBag);
+    return array;
+}
+
 static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
 {
     if (isSystem) {
@@ -2038,6 +2069,8 @@
         (void*) android_content_AssetManager_getArrayStringInfo },
     { "getArrayIntResource","(I)[I",
         (void*) android_content_AssetManager_getArrayIntResource },
+    { "getStyleAttributes","(I)[I",
+        (void*) android_content_AssetManager_getStyleAttributes },
 
     // Bookkeeping.
     { "init",           "(Z)V",
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 949f4ff..050037e 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -173,6 +173,12 @@
     return true;
 }
 
+static jboolean android_view_RenderNode_hasShadow(JNIEnv* env,
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().hasShadow();
+}
+
 static jboolean android_view_RenderNode_setClipToOutline(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, jboolean clipToOutline) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
@@ -491,6 +497,7 @@
     { "nSetOutlineConvexPath", "(JJF)Z", (void*) android_view_RenderNode_setOutlineConvexPath },
     { "nSetOutlineEmpty",      "(J)Z",   (void*) android_view_RenderNode_setOutlineEmpty },
     { "nSetOutlineNone",       "(J)Z",   (void*) android_view_RenderNode_setOutlineNone },
+    { "nHasShadow",            "(J)Z",   (void*) android_view_RenderNode_hasShadow },
     { "nSetClipToOutline",     "(JZ)Z",  (void*) android_view_RenderNode_setClipToOutline },
     { "nSetRevealClip",        "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
 
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index 85c2a09..84b7913 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -159,6 +159,11 @@
     animator->setInterpolator(interpolator);
 }
 
+static void setAllowRunningAsync(JNIEnv* env, jobject clazz, jlong animatorPtr, jboolean mayRunAsync) {
+    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
+    animator->setAllowRunningAsync(mayRunAsync);
+}
+
 static void start(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) {
     BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
     if (finishListener) {
@@ -191,6 +196,7 @@
     { "nGetDuration", "(J)J", (void*) getDuration },
     { "nSetStartDelay", "(JJ)V", (void*) setStartDelay },
     { "nSetInterpolator", "(JJ)V", (void*) setInterpolator },
+    { "nSetAllowRunningAsync", "(JZ)V", (void*) setAllowRunningAsync },
     { "nStart", "(JLandroid/view/RenderNodeAnimator;)V", (void*) start },
     { "nEnd", "(J)V", (void*) end },
 #endif
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 7e6d335..a8edb77 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -158,9 +158,11 @@
 
     // Marks the start of a frame, which will update the frame time and move all
     // next frame animations into the current frame
-    virtual void startFrame() {
-        mRootNode->doAttachAnimatingNodes(this);
-        AnimationContext::startFrame();
+    virtual void startFrame(TreeInfo::TraversalMode mode) {
+        if (mode == TreeInfo::MODE_FULL) {
+            mRootNode->doAttachAnimatingNodes(this);
+        }
+        AnimationContext::startFrame(mode);
     }
 
     // Runs any animations still left in mCurrentFrameAnimations
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7c5233c..72dd930 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -182,11 +182,11 @@
     <protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
 
     <protected-broadcast android:name="android.intent.action.HEADSET_PLUG" />
-    <protected-broadcast android:name="android.intent.action.ANALOG_AUDIO_DOCK_PLUG" />
-    <protected-broadcast android:name="android.intent.action.DIGITAL_AUDIO_DOCK_PLUG" />
-    <protected-broadcast android:name="android.intent.action.HDMI_AUDIO_PLUG" />
-    <protected-broadcast android:name="android.intent.action.USB_AUDIO_ACCESSORY_PLUG" />
-    <protected-broadcast android:name="android.intent.action.USB_AUDIO_DEVICE_PLUG" />
+    <protected-broadcast android:name="android.media.action.ANALOG_AUDIO_DOCK_PLUG" />
+    <protected-broadcast android:name="android.media.action.DIGITAL_AUDIO_DOCK_PLUG" />
+    <protected-broadcast android:name="android.media.action.HDMI_AUDIO_PLUG" />
+    <protected-broadcast android:name="android.media.action.USB_AUDIO_ACCESSORY_PLUG" />
+    <protected-broadcast android:name="android.media.action.USB_AUDIO_DEVICE_PLUG" />
 
     <protected-broadcast android:name="android.media.AUDIO_BECOMING_NOISY" />
     <protected-broadcast android:name="android.media.RINGER_MODE_CHANGED" />
diff --git a/core/res/res/values-mcc310-mnc260/config.xml b/core/res/res/values-mcc310-mnc260/config.xml
index 2f9394a..f8fff3b 100644
--- a/core/res/res/values-mcc310-mnc260/config.xml
+++ b/core/res/res/values-mcc310-mnc260/config.xml
@@ -25,6 +25,11 @@
     -->
     <integer name="config_mobile_mtu">1440</integer>
 
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+
     <!-- Values for GPS configuration (T-Mobile) -->
     <string-array translatable="false" name="config_gpsParameters">
         <item>CAPABILITEIS=0x33</item>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index cd5d55b..57ecd31 100644
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -38,10 +38,10 @@
         be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
     <bool name="imsServiceAllowTurnOff">false</bool>
 
-    <!-- Flag specifying whether VoLTE & VT should be allowed on device: independent of the
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
          carrier provisioning. If false: hard disabled. If true: then depends on carrier
          provisioning, availability etc -->
-    <bool name="config_mobile_allow_volte_vt">false</bool>
+    <bool name="config_carrier_volte_vt_available">false</bool>
 
     <bool name="config_auto_attach_data_on_creation">false</bool>
 
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d1cc1fd..cf4064f 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4341,6 +4341,8 @@
         <attr name="minDate" format="string" />
         <!-- The maximal date shown by this calendar view in mm/dd/yyyy format. -->
         <attr name="maxDate" format="string" />
+        <!-- The first day of week according to {@link java.util.Calendar}. -->
+        <attr name="firstDayOfWeek" />
         <!-- @hide The layout of the date picker. -->
         <attr name="internalLayout" format="reference"  />
         <!-- @hide The layout of the legacy DatePicker. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index e905a3a..10c2518e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -939,7 +939,7 @@
          {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK
          Intent.FLAG_ACTIVITY_MULTIPLE_TASK}. If the value of
          documentLaunchModes is <code>never</code> then any use of
-.........{@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT
+         {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT
          Intent.FLAG_ACTIVITY_NEW_DOCUMENT} to launch this activity will be ignored. -->
     <attr name="documentLaunchMode">
         <!-- The default mode, which will create a new task only when
@@ -994,6 +994,15 @@
          TaskDescription to change labels, colors and icons in the recent task list. -->
     <attr name="relinquishTaskIdentity" format="boolean" />
 
+    <!-- Indicate that it is okay for this activity be resumed while the previous
+         activity is in the process of pausing, without waiting for the previous pause
+         to complete.  Use this with caution: your activity can not acquire any exclusive
+         resources (such as opening the camera or recording audio) when it launches, or it
+         may conflict with the previous activity and fail.
+
+         <p>The default value of this attribute is <code>false</code>. -->
+    <attr name="resumeWhilePausing" format="boolean" />
+
     <!-- The <code>manifest</code> tag is the root of an
          <code>AndroidManifest.xml</code> file,
          describing the contents of an Android package (.apk) file.  One
@@ -1678,6 +1687,7 @@
         <attr name="maxRecents" />
         <attr name="autoRemoveFromRecents" />
         <attr name="relinquishTaskIdentity" />
+        <attr name="resumeWhilePausing" />
     </declare-styleable>
     
     <!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index d8e14a0..939cbf1 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -19,8 +19,8 @@
     <color name="background_material_dark">#ff212121</color>
     <color name="background_material_light">#fffafafa</color>
 
-    <color name="ripple_material_light">#20444444</color>
-    <color name="ripple_material_dark">#20ffffff</color>
+    <color name="ripple_material_light">#40000000</color>
+    <color name="ripple_material_dark">#40ffffff</color>
 
     <color name="button_material_dark">#ff5a595b</color>
     <color name="button_material_light">#ffd6d7d7</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b63b91d..f3b3077 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -771,6 +771,9 @@
          specified -->
     <string name="default_wallpaper_component" translatable="false">@null</string>
 
+    <!-- Component name of the built in wallpaper used to display bitmap wallpapers. This must not be null. -->
+    <string name="image_wallpaper_component" translatable="false">com.android.systemui/com.android.systemui.ImageWallpaper</string>
+
     <!-- True if WallpaperService is enabled -->
     <bool name="config_enableWallpaperService">true</bool>
 
@@ -1671,10 +1674,13 @@
         be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
     <bool name="imsServiceAllowTurnOff">true</bool>
 
-    <!-- Flag specifying whether VoLTE & VT should be allowed on device: independent of the
+    <!-- Flag specifying whether VoLTE & VT is availasble on device -->
+    <bool name="config_device_volte_vt_available">false</bool>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
          carrier provisioning. If false: hard disabled. If true: then depends on carrier
          provisioning, availability etc -->
-    <bool name="config_mobile_allow_volte_vt">true</bool>
+    <bool name="config_carrier_volte_vt_available">false</bool>
 
     <bool name="config_networkSamplingWakesDevice">true</bool>
 
@@ -1695,9 +1701,13 @@
          and adds page info " x/y". This config is used to set which carrier doesn't
          support EMS and whether page info should be added at the beginning or the end.
          We use tag 'prefix' for position beginning and 'suffix' for position end.
-         Examples: <item>311480;prefix</item> <item>310260;suffix</item>
+         And use gid to distinguish different carriers which using same mcc and mnc.
+         Examples: <item>simOperatorNumber;position;gid(optional)</item>>
     -->
-    <string-array translatable="false" name="no_ems_support_sim_operators" />
+    <string-array translatable="false" name="no_ems_support_sim_operators">
+        <!-- VZW -->
+        <item>20404;suffix;BAE0000000000000</item>
+    </string-array>
 
     <bool name="config_auto_attach_data_on_creation">true</bool>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index a4c3474..5b047f7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2266,7 +2266,7 @@
   <public type="attr" name="windowReenterTransition" />
   <public type="attr" name="windowSharedElementReturnTransition" />
   <public type="attr" name="windowSharedElementReenterTransition" />
-  <public type="attr" name="__removed1" />
+  <public type="attr" name="resumeWhilePausing" />
   <public type="attr" name="datePickerMode"/>
   <public type="attr" name="timePickerMode"/>
   <public type="attr" name="inset" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1b0f9c4..01e6e76 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1634,6 +1634,7 @@
   <java-symbol type="string" name="hardware" />
   <java-symbol type="string" name="heavy_weight_notification" />
   <java-symbol type="string" name="heavy_weight_notification_detail" />
+  <java-symbol type="string" name="image_wallpaper_component" />
   <java-symbol type="string" name="input_method_binding_label" />
   <java-symbol type="string" name="launch_warning_original" />
   <java-symbol type="string" name="launch_warning_replace" />
@@ -1969,7 +1970,8 @@
   <java-symbol type="attr" name="preferenceFragmentStyle" />
   <java-symbol type="bool" name="skipHoldBeforeMerge" />
   <java-symbol type="bool" name="imsServiceAllowTurnOff" />
-  <java-symbol type="bool" name="config_mobile_allow_volte_vt" />
+  <java-symbol type="bool" name="config_device_volte_vt_available" />
+  <java-symbol type="bool" name="config_carrier_volte_vt_available" />
   <java-symbol type="bool" name="useImsAlwaysForEmergencyCall" />
   <java-symbol type="attr" name="touchscreenBlocksFocus" />
   <java-symbol type="layout" name="resolver_list_with_default" />
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
index a3c5351..77e1c530 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
@@ -54,7 +54,7 @@
     protected static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
     protected static final int WIFI_SCAN_TIMEOUT = 50 * 1000; // 50 seconds
     protected static final int SHORT_TIMEOUT = 5 * 1000; // 5 seconds
-    protected static final long LONG_TIMEOUT = 50 * 1000;  // 50 seconds
+    protected static final long LONG_TIMEOUT = 2 * 60 * 1000;  // 2 minutes
     protected static final long WIFI_CONNECTION_TIMEOUT = 5 * 60 * 1000; // 5 minutes
     // 2 minutes timer between wifi stop and start
     protected static final long  WIFI_STOP_START_INTERVAL = 2 * 60 * 1000; // 2 minutes
diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
index ed8b7f7..a11e49b 100755
--- a/core/tests/inputmethodtests/run_core_inputmethod_test.sh
+++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
@@ -15,7 +15,7 @@
 
 if [[ $rebuild == true ]]; then
   make -j4 FrameworksCoreInputMethodTests
-  TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreInputMethodTests.apk
+  TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreInputMethodTests/FrameworksCoreInputMethodTests.apk
   COMMAND="adb install -r $TESTAPP"
   echo $COMMAND
   $COMMAND
diff --git a/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
index cc4a7c4..b6a03d9 100644
--- a/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
+++ b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
@@ -26,14 +26,12 @@
 
 import java.util.Objects;
 
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_NOT_FEASIBLE;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_UNSPECIFIED;
+import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+import static android.view.inputmethod.CursorAnchorInfo.FLAG_IS_RTL;
 
 public class CursorAnchorInfoTest extends InstrumentationTestCase {
-    private static final RectF[] MANY_RECTS = new RectF[] {
+    private static final RectF[] MANY_BOUNDS = new RectF[] {
             new RectF(101.0f, 201.0f, 301.0f, 401.0f),
             new RectF(102.0f, 202.0f, 302.0f, 402.0f),
             new RectF(103.0f, 203.0f, 303.0f, 403.0f),
@@ -55,25 +53,25 @@
             new RectF(119.0f, 219.0f, 319.0f, 419.0f),
     };
     private static final int[] MANY_FLAGS_ARRAY = new int[] {
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_INVISIBLE,
-        CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_NOT_FEASIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
-        CHARACTER_RECT_TYPE_NOT_FEASIBLE,
-        CHARACTER_RECT_TYPE_NOT_FEASIBLE,
+        FLAG_HAS_INVISIBLE_REGION,
+        FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION,
+        FLAG_HAS_VISIBLE_REGION,
+        FLAG_HAS_VISIBLE_REGION,
+        FLAG_HAS_VISIBLE_REGION,
+        FLAG_HAS_VISIBLE_REGION,
+        FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+        FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+        FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL,
+        FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+        FLAG_HAS_VISIBLE_REGION,
+        FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+        FLAG_HAS_VISIBLE_REGION,
+        FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+        FLAG_HAS_VISIBLE_REGION,
+        FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+        FLAG_HAS_VISIBLE_REGION,
+        FLAG_HAS_INVISIBLE_REGION,
+        FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL,
     };
 
     @SmallTest
@@ -82,11 +80,13 @@
         final int SELECTION_END = 40;
         final int COMPOSING_TEXT_START = 32;
         final String COMPOSING_TEXT = "test";
-        final boolean INSERTION_MARKER_CLIPPED = true;
+        final int INSERTION_MARKER_FLAGS =
+                FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL;
         final float INSERTION_MARKER_HORIZONTAL = 10.5f;
         final float INSERTION_MARKER_TOP = 100.1f;
         final float INSERTION_MARKER_BASELINE = 110.4f;
         final float INSERTION_MARKER_BOTOM = 111.0f;
+
         Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX);
         TRANSFORM_MATRIX.setScale(10.0f, 20.0f);
 
@@ -94,13 +94,13 @@
         builder.setSelectionRange(SELECTION_START, SELECTION_END)
                 .setComposingText(COMPOSING_TEXT_START, COMPOSING_TEXT)
                 .setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
-                        INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM,
-                        INSERTION_MARKER_CLIPPED)
+                        INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS)
                 .setMatrix(TRANSFORM_MATRIX);
-        for (int i = 0; i < MANY_RECTS.length; i++) {
-            final RectF rect = MANY_RECTS[i];
+        for (int i = 0; i < MANY_BOUNDS.length; i++) {
+            final RectF bounds = MANY_BOUNDS[i];
             final int flags = MANY_FLAGS_ARRAY[i];
-            builder.addCharacterRect(i, rect.left, rect.top, rect.right, rect.bottom, flags);
+            builder.addCharacterBounds(i, bounds.left, bounds.top, bounds.right, bounds.bottom,
+                    flags);
         }
 
         final CursorAnchorInfo info = builder.build();
@@ -108,26 +108,24 @@
         assertEquals(SELECTION_END, info.getSelectionEnd());
         assertEquals(COMPOSING_TEXT_START, info.getComposingTextStart());
         assertTrue(TextUtils.equals(COMPOSING_TEXT, info.getComposingText()));
-        assertTrue(info.isInsertionMarkerClipped());
+        assertEquals(INSERTION_MARKER_FLAGS, info.getInsertionMarkerFlags());
         assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal());
         assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop());
         assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline());
         assertEquals(INSERTION_MARKER_BOTOM, info.getInsertionMarkerBottom());
         assertEquals(TRANSFORM_MATRIX, info.getMatrix());
-        for (int i = 0; i < MANY_RECTS.length; i++) {
-            final RectF expectedRect = MANY_RECTS[i];
-            assertEquals(expectedRect, info.getCharacterRect(i));
+        for (int i = 0; i < MANY_BOUNDS.length; i++) {
+            final RectF expectedBounds = MANY_BOUNDS[i];
+            assertEquals(expectedBounds, info.getCharacterRect(i));
         }
         assertNull(info.getCharacterRect(-1));
-        assertNull(info.getCharacterRect(MANY_RECTS.length + 1));
+        assertNull(info.getCharacterRect(MANY_BOUNDS.length + 1));
         for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
             final int expectedFlags = MANY_FLAGS_ARRAY[i];
             assertEquals(expectedFlags, info.getCharacterRectFlags(i));
         }
-        assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
-                info.getCharacterRectFlags(-1));
-        assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
-                info.getCharacterRectFlags(MANY_RECTS.length + 1));
+        assertEquals(0, info.getCharacterRectFlags(-1));
+        assertEquals(0, info.getCharacterRectFlags(MANY_BOUNDS.length + 1));
 
         // Make sure that the builder can reproduce the same object.
         final CursorAnchorInfo info2 = builder.build();
@@ -135,25 +133,24 @@
         assertEquals(SELECTION_END, info2.getSelectionEnd());
         assertEquals(COMPOSING_TEXT_START, info2.getComposingTextStart());
         assertTrue(TextUtils.equals(COMPOSING_TEXT, info2.getComposingText()));
-        assertTrue(info2.isInsertionMarkerClipped());
+        assertEquals(INSERTION_MARKER_FLAGS, info2.getInsertionMarkerFlags());
         assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal());
         assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop());
         assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline());
         assertEquals(INSERTION_MARKER_BOTOM, info2.getInsertionMarkerBottom());
         assertEquals(TRANSFORM_MATRIX, info2.getMatrix());
-        for (int i = 0; i < MANY_RECTS.length; i++) {
-            final RectF expectedRect = MANY_RECTS[i];
-            assertEquals(expectedRect, info2.getCharacterRect(i));
+        for (int i = 0; i < MANY_BOUNDS.length; i++) {
+            final RectF expectedBounds = MANY_BOUNDS[i];
+            assertEquals(expectedBounds, info2.getCharacterRect(i));
         }
         assertNull(info2.getCharacterRect(-1));
-        assertNull(info2.getCharacterRect(MANY_RECTS.length + 1));
+        assertNull(info2.getCharacterRect(MANY_BOUNDS.length + 1));
         for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
             final int expectedFlags = MANY_FLAGS_ARRAY[i];
             assertEquals(expectedFlags, info2.getCharacterRectFlags(i));
         }
-        assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, info2.getCharacterRectFlags(-1));
-        assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
-                info2.getCharacterRectFlags(MANY_RECTS.length + 1));
+        assertEquals(0, info2.getCharacterRectFlags(-1));
+        assertEquals(0, info2.getCharacterRectFlags(MANY_BOUNDS.length + 1));
         assertEquals(info, info2);
         assertEquals(info.hashCode(), info2.hashCode());
 
@@ -163,25 +160,24 @@
         assertEquals(SELECTION_END, info3.getSelectionEnd());
         assertEquals(COMPOSING_TEXT_START, info3.getComposingTextStart());
         assertTrue(TextUtils.equals(COMPOSING_TEXT, info3.getComposingText()));
-        assertTrue(info3.isInsertionMarkerClipped());
+        assertEquals(INSERTION_MARKER_FLAGS, info3.getInsertionMarkerFlags());
         assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal());
         assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop());
         assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline());
         assertEquals(INSERTION_MARKER_BOTOM, info3.getInsertionMarkerBottom());
         assertEquals(TRANSFORM_MATRIX, info3.getMatrix());
-        for (int i = 0; i < MANY_RECTS.length; i++) {
-            final RectF expectedRect = MANY_RECTS[i];
-            assertEquals(expectedRect, info3.getCharacterRect(i));
+        for (int i = 0; i < MANY_BOUNDS.length; i++) {
+            final RectF expectedBounds = MANY_BOUNDS[i];
+            assertEquals(expectedBounds, info3.getCharacterRect(i));
         }
         assertNull(info3.getCharacterRect(-1));
-        assertNull(info3.getCharacterRect(MANY_RECTS.length + 1));
+        assertNull(info3.getCharacterRect(MANY_BOUNDS.length + 1));
         for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
             final int expectedFlags = MANY_FLAGS_ARRAY[i];
             assertEquals(expectedFlags, info3.getCharacterRectFlags(i));
         }
-        assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, info3.getCharacterRectFlags(-1));
-        assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
-                info3.getCharacterRectFlags(MANY_RECTS.length + 1));
+        assertEquals(0, info3.getCharacterRectFlags(-1));
+        assertEquals(0, info3.getCharacterRectFlags(MANY_BOUNDS.length + 1));
         assertEquals(info.hashCode(), info3.hashCode());
 
         builder.reset();
@@ -190,7 +186,7 @@
         assertEquals(-1, uninitializedInfo.getSelectionEnd());
         assertEquals(-1, uninitializedInfo.getComposingTextStart());
         assertNull(uninitializedInfo.getComposingText());
-        assertFalse(uninitializedInfo.isInsertionMarkerClipped());
+        assertEquals(0, uninitializedInfo.getInsertionMarkerFlags());
         assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal());
         assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop());
         assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline());
@@ -218,7 +214,7 @@
         final int SELECTION_END1 = 7;
         final String COMPOSING_TEXT1 = "0123456789";
         final int COMPOSING_TEXT_START1 = 0;
-        final boolean INSERTION_MARKER_CLIPPED1 = true;
+        final int INSERTION_MARKER_FLAGS1 = FLAG_HAS_VISIBLE_REGION;
         final float INSERTION_MARKER_HORIZONTAL1 = 10.5f;
         final float INSERTION_MARKER_TOP1 = 100.1f;
         final float INSERTION_MARKER_BASELINE1 = 110.4f;
@@ -227,7 +223,8 @@
         final int SELECTION_END2 = 8;
         final String COMPOSING_TEXT2 = "9876543210";
         final int COMPOSING_TEXT_START2 = 3;
-        final boolean INSERTION_MARKER_CLIPPED2 = false;
+        final int INSERTION_MARKER_FLAGS2 =
+                FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL;
         final float INSERTION_MARKER_HORIZONTAL2 = 14.5f;
         final float INSERTION_MARKER_TOP2 = 200.1f;
         final float INSERTION_MARKER_BASELINE2 = 210.4f;
@@ -265,10 +262,10 @@
         assertEquals(
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         Float.NaN, Float.NaN, Float.NaN, Float.NaN,
-                        INSERTION_MARKER_CLIPPED1).build(),
+                        INSERTION_MARKER_FLAGS1).build(),
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         Float.NaN, Float.NaN, Float.NaN, Float.NaN,
-                        INSERTION_MARKER_CLIPPED1).build());
+                        INSERTION_MARKER_FLAGS1).build());
 
         // Check Matrix.
         assertEquals(
@@ -290,74 +287,74 @@
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build(),
+                        INSERTION_MARKER_FLAGS1).build(),
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build());
+                        INSERTION_MARKER_FLAGS1).build());
         assertNotEquals(
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         Float.NaN, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build(),
+                        INSERTION_MARKER_FLAGS1).build(),
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build());
+                        INSERTION_MARKER_FLAGS1).build());
         assertNotEquals(
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build(),
+                        INSERTION_MARKER_FLAGS1).build(),
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build());
+                        INSERTION_MARKER_FLAGS1).build());
         assertNotEquals(
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build(),
+                        INSERTION_MARKER_FLAGS1).build(),
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP2,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build());
+                        INSERTION_MARKER_FLAGS1).build());
         assertNotEquals(
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build(),
+                        INSERTION_MARKER_FLAGS1).build(),
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE2, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build());
+                        INSERTION_MARKER_FLAGS1).build());
         assertNotEquals(
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build(),
+                        INSERTION_MARKER_FLAGS1).build(),
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build());
+                        INSERTION_MARKER_FLAGS1).build());
         assertNotEquals(
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build(),
+                        INSERTION_MARKER_FLAGS1).build(),
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM2,
-                        INSERTION_MARKER_CLIPPED1).build());
+                        INSERTION_MARKER_FLAGS1).build());
         assertNotEquals(
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED1).build(),
+                        INSERTION_MARKER_FLAGS1).build(),
                 new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
                         INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
                         INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_CLIPPED2).build());
+                        INSERTION_MARKER_FLAGS2).build());
     }
 
     @SmallTest
@@ -394,7 +391,7 @@
         final int SELECTION_END = 40;
         final int COMPOSING_TEXT_START = 32;
         final String COMPOSING_TEXT = "test";
-        final boolean INSERTION_MARKER_CLIPPED = true;
+        final int INSERTION_MARKER_FLAGS = FLAG_HAS_VISIBLE_REGION;
         final float INSERTION_MARKER_HORIZONTAL = 10.5f;
         final float INSERTION_MARKER_TOP = 100.1f;
         final float INSERTION_MARKER_BASELINE = 110.4f;
@@ -416,7 +413,7 @@
             }
 
             builder.setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
-                    INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_CLIPPED);
+                    INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS);
             try {
                 // Coordinate transformation matrix is required if no positional information is
                 // specified.
@@ -438,19 +435,10 @@
     }
 
     @SmallTest
-    public void testBuilderAddCharacterRect() throws Exception {
+    public void testBuilderAddCharacterBounds() throws Exception {
         // A negative index should be rejected.
         try {
-            new Builder().addCharacterRect(-1, 0.0f, 0.0f, 0.0f, 0.0f,
-                    CHARACTER_RECT_TYPE_FULLY_VISIBLE);
-            assertTrue(false);
-        } catch (IllegalArgumentException ex) {
-        }
-
-        // CHARACTER_RECT_TYPE_UNSPECIFIED is not allowed.
-        try {
-            new Builder().addCharacterRect(0, 0.0f, 0.0f, 0.0f, 0.0f,
-                    CHARACTER_RECT_TYPE_UNSPECIFIED);
+            new Builder().addCharacterBounds(-1, 0.0f, 0.0f, 0.0f, 0.0f, FLAG_HAS_VISIBLE_REGION);
             assertTrue(false);
         } catch (IllegalArgumentException ex) {
         }
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 5a3e3a3..3cb5210 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -470,19 +470,6 @@
     }
 
     /**
-     * Specifies a tint and blending mode for this drawable.
-     * <p>
-     * Setting a color filter via {@link #setColorFilter(ColorFilter)} overrides
-     * tint.
-     *
-     * @param tint Color state list to use for tinting this drawable, or null to
-     *            clear the tint
-     * @param tintMode A Porter-Duff blending mode
-     * @hide TODO: Was in L-preview, remove this API for release
-     */
-    public void setTint(ColorStateList tint, PorterDuff.Mode tintMode) {}
-
-    /**
      * Specifies a tint for this drawable.
      * <p>
      * Setting a color filter via {@link #setColorFilter(ColorFilter)} overrides
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index 43922b8..6f95f91 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -22,6 +22,7 @@
 import android.animation.TimeInterpolator;
 import android.graphics.Canvas;
 import android.graphics.CanvasProperty;
+import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Paint.Style;
 import android.graphics.Rect;
@@ -58,7 +59,7 @@
     private final Rect mBounds;
 
     /** Full-opacity color for drawing this ripple. */
-    private int mColor;
+    private int mColorOpaque;
 
     /** Maximum ripple radius. */
     private float mOuterRadius;
@@ -120,7 +121,7 @@
     }
 
     public void setup(int maxRadius, int color, float density) {
-        mColor = color | 0xFF000000;
+        mColorOpaque = color | 0xFF000000;
 
         if (maxRadius != RippleDrawable.RADIUS_AUTO) {
             mHasMaxRadius = true;
@@ -236,6 +237,9 @@
         if (N > 0) {
             cancelHardwareAnimations(false);
 
+            // We canceled old animations, but we're about to run new ones.
+            mHardwareAnimating = true;
+
             for (int i = 0; i < N; i++) {
                 pendingAnimations.get(i).setTarget(c);
                 pendingAnimations.get(i).start();
@@ -253,9 +257,8 @@
     private boolean drawSoftware(Canvas c, Paint p) {
         boolean hasContent = false;
 
-        // Cache the paint alpha so we can restore it later.
-        final int paintAlpha = p.getAlpha();
-        final int alpha = (int) (paintAlpha * mOpacity + 0.5f);
+        p.setColor(mColorOpaque);
+        final int alpha = (int) (255 * mOpacity + 0.5f);
         final float radius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
         if (alpha > 0 && radius > 0) {
             final float x = MathUtils.lerp(
@@ -268,8 +271,6 @@
             hasContent = true;
         }
 
-        p.setAlpha(paintAlpha);
-
         return hasContent;
     }
 
@@ -369,7 +370,7 @@
         final float startRadius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
         final Paint paint = getTempPaint();
         paint.setAntiAlias(true);
-        paint.setColor(mColor);
+        paint.setColor(mColorOpaque);
         paint.setAlpha((int) (255 * mOpacity + 0.5f));
         paint.setStyle(Style.FILL);
         mPropPaint = CanvasProperty.createPaint(paint);
@@ -402,6 +403,12 @@
 
         mHardwareAnimating = true;
 
+        // Set up the software values to match the hardware end values.
+        mOpacity = 0;
+        mTweenX = 1;
+        mTweenY = 1;
+        mTweenRadius = 1;
+
         invalidateSelf();
     }
 
@@ -412,7 +419,7 @@
     public void jump() {
         mCanceled = true;
         endSoftwareAnimations();
-        endHardwareAnimations();
+        cancelHardwareAnimations(true);
         mCanceled = false;
     }
 
@@ -438,24 +445,6 @@
         }
     }
 
-    private void endHardwareAnimations() {
-        final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
-        final int N = runningAnimations.size();
-        for (int i = 0; i < N; i++) {
-            runningAnimations.get(i).end();
-        }
-        runningAnimations.clear();
-
-        // Abort any pending animations. Since we always have a completion
-        // listener on a pending animation, we also need to remove ourselves.
-        if (!mPendingAnimations.isEmpty()) {
-            mPendingAnimations.clear();
-            removeSelf();
-        }
-
-        mHardwareAnimating = false;
-    }
-
     private Paint getTempPaint() {
         if (mTempPaint == null) {
             mTempPaint = new Paint();
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index 80ecea3..bc6f5fb 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -22,6 +22,7 @@
 import android.animation.TimeInterpolator;
 import android.graphics.Canvas;
 import android.graphics.CanvasProperty;
+import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Paint.Style;
 import android.graphics.Rect;
@@ -46,8 +47,6 @@
     private static final float WAVE_OUTER_SIZE_INFLUENCE_MAX = 200f;
     private static final float WAVE_OUTER_SIZE_INFLUENCE_MIN = 40f;
 
-    private static final long RIPPLE_ENTER_DELAY = 80;
-
     // Hardware animators.
     private final ArrayList<RenderNodeAnimator> mRunningAnimations =
             new ArrayList<RenderNodeAnimator>();
@@ -60,7 +59,10 @@
     private final Rect mBounds;
 
     /** Full-opacity color for drawing this ripple. */
-    private int mColor;
+    private int mColorOpaque;
+
+    /** Maximum alpha value for drawing this ripple. */
+    private int mColorAlpha;
 
     /** Maximum ripple radius. */
     private float mOuterRadius;
@@ -103,7 +105,8 @@
     }
 
     public void setup(int maxRadius, int color, float density) {
-        mColor = color | 0xFF000000;
+        mColorOpaque = color | 0xFF000000;
+        mColorAlpha = Color.alpha(color);
 
         if (maxRadius != RippleDrawable.RADIUS_AUTO) {
             mHasMaxRadius = true;
@@ -159,6 +162,11 @@
         return hasContent;
     }
 
+    public boolean shouldDraw() {
+        final int outerAlpha = (int) (mColorAlpha * mOuterOpacity + 0.5f);
+        return mCanUseHardware && mHardwareAnimating || outerAlpha > 0 && mOuterRadius > 0;
+    }
+
     private boolean drawHardware(HardwareCanvas c) {
         // If we have any pending hardware animations, cancel any running
         // animations and start those now.
@@ -167,6 +175,9 @@
         if (N > 0) {
             cancelHardwareAnimations(false);
 
+            // We canceled old animations, but we're about to run new ones.
+            mHardwareAnimating = true;
+
             for (int i = 0; i < N; i++) {
                 pendingAnimations.get(i).setTarget(c);
                 pendingAnimations.get(i).start();
@@ -184,10 +195,8 @@
     private boolean drawSoftware(Canvas c, Paint p) {
         boolean hasContent = false;
 
-        // Cache the paint alpha so we can restore it later.
-        final int paintAlpha = p.getAlpha();
-
-        final int outerAlpha = (int) (paintAlpha * mOuterOpacity + 0.5f);
+        p.setColor(mColorOpaque);
+        final int outerAlpha = (int) (mColorAlpha * mOuterOpacity + 0.5f);
         if (outerAlpha > 0 && mOuterRadius > 0) {
             p.setAlpha(outerAlpha);
             p.setStyle(Style.FILL);
@@ -195,8 +204,6 @@
             hasContent = true;
         }
 
-        p.setAlpha(paintAlpha);
-
         return hasContent;
     }
 
@@ -248,25 +255,25 @@
         // Determine at what time the inner and outer opacity intersect.
         // inner(t) = mOpacity - t * WAVE_OPACITY_DECAY_VELOCITY / 1000
         // outer(t) = mOuterOpacity + t * WAVE_OUTER_OPACITY_VELOCITY / 1000
-        final int outerInflection = Math.max(0, (int) (1000 * (1 - mOuterOpacity)
+        final int inflectionDuration = Math.max(0, (int) (1000 * (1 - mOuterOpacity)
                 / (WAVE_OPACITY_DECAY_VELOCITY + outerOpacityVelocity) + 0.5f));
-        final int inflectionOpacity = (int) (255 * (mOuterOpacity + outerInflection
-                * outerOpacityVelocity * outerSizeInfluence / 1000) + 0.5f);
+        final int inflectionOpacity = (int) (mColorAlpha * (mOuterOpacity
+                + inflectionDuration * outerOpacityVelocity * outerSizeInfluence / 1000) + 0.5f);
 
         if (mCanUseHardware) {
-            exitHardware(opacityDuration, outerInflection, inflectionOpacity);
+            exitHardware(opacityDuration, inflectionDuration, inflectionOpacity);
         } else {
-            exitSoftware(opacityDuration, outerInflection, inflectionOpacity);
+            exitSoftware(opacityDuration, inflectionDuration, inflectionOpacity);
         }
     }
 
-    private void exitHardware(int opacityDuration, int outerInflection, int inflectionOpacity) {
+    private void exitHardware(int opacityDuration, int inflectionDuration, int inflectionOpacity) {
         mPendingAnimations.clear();
 
         final Paint outerPaint = getTempPaint();
         outerPaint.setAntiAlias(true);
-        outerPaint.setColor(mColor);
-        outerPaint.setAlpha((int) (255 * mOuterOpacity + 0.5f));
+        outerPaint.setColor(mColorOpaque);
+        outerPaint.setAlpha((int) (mColorAlpha * mOuterOpacity + 0.5f));
         outerPaint.setStyle(Style.FILL);
         mPropOuterPaint = CanvasProperty.createPaint(outerPaint);
         mPropOuterRadius = CanvasProperty.createFloat(mOuterRadius);
@@ -274,21 +281,21 @@
         mPropOuterY = CanvasProperty.createFloat(mOuterY);
 
         final RenderNodeAnimator outerOpacityAnim;
-        if (outerInflection > 0) {
+        if (inflectionDuration > 0) {
             // Outer opacity continues to increase for a bit.
-            outerOpacityAnim = new RenderNodeAnimator(
-                    mPropOuterPaint, RenderNodeAnimator.PAINT_ALPHA, inflectionOpacity);
-            outerOpacityAnim.setDuration(outerInflection);
+            outerOpacityAnim = new RenderNodeAnimator(mPropOuterPaint,
+                    RenderNodeAnimator.PAINT_ALPHA, inflectionOpacity);
+            outerOpacityAnim.setDuration(inflectionDuration);
             outerOpacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
 
             // Chain the outer opacity exit animation.
-            final int outerDuration = opacityDuration - outerInflection;
+            final int outerDuration = opacityDuration - inflectionDuration;
             if (outerDuration > 0) {
                 final RenderNodeAnimator outerFadeOutAnim = new RenderNodeAnimator(
                         mPropOuterPaint, RenderNodeAnimator.PAINT_ALPHA, 0);
                 outerFadeOutAnim.setDuration(outerDuration);
                 outerFadeOutAnim.setInterpolator(LINEAR_INTERPOLATOR);
-                outerFadeOutAnim.setStartDelay(outerInflection);
+                outerFadeOutAnim.setStartDelay(inflectionDuration);
                 outerFadeOutAnim.setStartValue(inflectionOpacity);
                 outerFadeOutAnim.addListener(mAnimationListener);
 
@@ -320,7 +327,7 @@
      */
     public void jump() {
         endSoftwareAnimations();
-        endHardwareAnimations();
+        cancelHardwareAnimations(true);
     }
 
     private void endSoftwareAnimations() {
@@ -330,23 +337,6 @@
         }
     }
 
-    private void endHardwareAnimations() {
-        final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
-        final int N = runningAnimations.size();
-        for (int i = 0; i < N; i++) {
-            runningAnimations.get(i).end();
-        }
-        runningAnimations.clear();
-
-        // Abort any pending animations. Since we always have a completion
-        // listener on a pending animation, we also need to remove ourselves.
-        if (!mPendingAnimations.isEmpty()) {
-            mPendingAnimations.clear();
-        }
-
-        mHardwareAnimating = false;
-    }
-
     private Paint getTempPaint() {
         if (mTempPaint == null) {
             mTempPaint = new Paint();
@@ -354,18 +344,18 @@
         return mTempPaint;
     }
 
-    private void exitSoftware(int opacityDuration, int outerInflection, int inflectionOpacity) {
+    private void exitSoftware(int opacityDuration, int inflectionDuration, int inflectionOpacity) {
         final ObjectAnimator outerOpacityAnim;
-        if (outerInflection > 0) {
+        if (inflectionDuration > 0) {
             // Outer opacity continues to increase for a bit.
             outerOpacityAnim = ObjectAnimator.ofFloat(this,
                     "outerOpacity", inflectionOpacity / 255.0f);
             outerOpacityAnim.setAutoCancel(true);
-            outerOpacityAnim.setDuration(outerInflection);
+            outerOpacityAnim.setDuration(inflectionDuration);
             outerOpacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
 
             // Chain the outer opacity exit animation.
-            final int outerDuration = opacityDuration - outerInflection;
+            final int outerDuration = opacityDuration - inflectionDuration;
             if (outerDuration > 0) {
                 outerOpacityAnim.addListener(new AnimatorListenerAdapter() {
                     @Override
@@ -446,14 +436,4 @@
             mHardwareAnimating = false;
         }
     };
-
-    /**
-    * Interpolator with a smooth log deceleration
-    */
-    private static final class LogInterpolator implements TimeInterpolator {
-        @Override
-        public float getInterpolation(float input) {
-            return 1 - (float) Math.pow(400, -input * 1.4);
-        }
-    }
 }
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index fa762b7..b05fb61 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -242,7 +242,7 @@
 
     @Override
     protected boolean onStateChange(int[] stateSet) {
-        super.onStateChange(stateSet);
+        final boolean changed = super.onStateChange(stateSet);
 
         boolean enabled = false;
         boolean pressed = false;
@@ -263,19 +263,7 @@
         setRippleActive(enabled && pressed);
         setBackgroundActive(focused || (enabled && pressed));
 
-        // Update the paint color. Only applicable when animated in software.
-        if (mRipplePaint != null && mState.mColor != null) {
-            final ColorStateList stateList = mState.mColor;
-            final int newColor = stateList.getColorForState(stateSet, 0);
-            final int oldColor = mRipplePaint.getColor();
-            if (oldColor != newColor) {
-                mRipplePaint.setColor(newColor);
-                invalidateSelf();
-                return true;
-            }
-        }
-
-        return false;
+        return changed;
     }
 
     private void setRippleActive(boolean active) {
@@ -587,6 +575,10 @@
             ripples[i].onHotspotBoundsChanged();
         }
 
+        if (mRipple != null) {
+            mRipple.onHotspotBoundsChanged();
+        }
+
         if (mBackground != null) {
             mBackground.onHotspotBoundsChanged();
         }
@@ -617,17 +609,23 @@
         final boolean drawNonMaskContent = mLayerState.mNum > (hasMask ? 1 : 0);
         final boolean drawMask = hasMask && mMask.getOpacity() != PixelFormat.OPAQUE;
         final Rect bounds = getDirtyBounds();
+        final int saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
+        canvas.clipRect(bounds);
 
         // If we have content, draw it into a layer first.
-        final int contentLayer = drawNonMaskContent ?
-                drawContentLayer(canvas, bounds, SRC_OVER) : -1;
+        final int contentLayer;
+        if (drawNonMaskContent) {
+            contentLayer = drawContentLayer(canvas, bounds, SRC_OVER);
+        } else {
+            contentLayer = -1;
+        }
 
         // Next, try to draw the ripples (into a layer if necessary). If we need
         // to mask against the underlying content, set the xfermode to SRC_ATOP.
         final PorterDuffXfermode xfermode = (hasMask || !drawNonMaskContent) ? SRC_OVER : SRC_ATOP;
 
         // If we have a background and a non-opaque mask, draw the masking layer.
-        final int backgroundLayer = drawBackgroundLayer(canvas, bounds, xfermode);
+        final int backgroundLayer = drawBackgroundLayer(canvas, bounds, xfermode, drawMask);
         if (backgroundLayer >= 0) {
             if (drawMask) {
                 drawMaskingLayer(canvas, bounds, DST_IN);
@@ -644,10 +642,13 @@
             canvas.restoreToCount(rippleLayer);
         }
 
-        // Composite the layers if needed.
-        if (contentLayer >= 0) {
-            canvas.restoreToCount(contentLayer);
+        // If we failed to draw anything, at least draw a color so that
+        // invalidation works correctly.
+        if (contentLayer < 0 && backgroundLayer < 0 && rippleLayer < 0) {
+            canvas.drawColor(Color.TRANSPARENT);
         }
+
+        canvas.restoreToCount(saveCount);
     }
 
     /**
@@ -711,81 +712,29 @@
         return restoreToCount;
     }
 
-    private int drawBackgroundLayer(Canvas canvas, Rect bounds, PorterDuffXfermode mode) {
-        // Separate the ripple color and alpha channel. The alpha will be
-        // applied when we merge the ripples down to the canvas.
-        final int rippleARGB;
-        if (mState.mColor != null) {
-            rippleARGB = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
-        } else {
-            rippleARGB = Color.TRANSPARENT;
+    private int drawBackgroundLayer(
+            Canvas canvas, Rect bounds, PorterDuffXfermode mode, boolean drawMask) {
+        int saveCount = -1;
+
+        if (mBackground != null && mBackground.shouldDraw()) {
+            // TODO: We can avoid saveLayer here if we push the xfermode into
+            // the background's render thread animator at exit() time.
+            if (drawMask || mode != SRC_OVER) {
+                saveCount = canvas.saveLayer(bounds.left, bounds.top, bounds.right,
+                        bounds.bottom, getMaskingPaint(mode));
+            }
+
+            final float x = mHotspotBounds.exactCenterX();
+            final float y = mHotspotBounds.exactCenterY();
+            canvas.translate(x, y);
+            mBackground.draw(canvas, getRipplePaint());
+            canvas.translate(-x, -y);
         }
 
-        if (mRipplePaint == null) {
-            mRipplePaint = new Paint();
-            mRipplePaint.setAntiAlias(true);
-        }
-
-        final int rippleAlpha = Color.alpha(rippleARGB);
-        final Paint ripplePaint = mRipplePaint;
-        ripplePaint.setColor(rippleARGB);
-        ripplePaint.setAlpha(0xFF);
-
-        boolean drewRipples = false;
-        int restoreToCount = -1;
-        int restoreTranslate = -1;
-
-        // Draw background.
-        final RippleBackground background = mBackground;
-        if (background != null) {
-            // If we're masking the ripple layer, make sure we have a layer
-            // first. This will merge SRC_OVER (directly) onto the canvas.
-            final Paint maskingPaint = getMaskingPaint(mode);
-            maskingPaint.setAlpha(rippleAlpha);
-            restoreToCount = canvas.saveLayer(bounds.left, bounds.top,
-                    bounds.right, bounds.bottom, maskingPaint);
-
-            restoreTranslate = canvas.save();
-            // Translate the canvas to the current hotspot bounds.
-            canvas.translate(mHotspotBounds.exactCenterX(), mHotspotBounds.exactCenterY());
-
-            drewRipples = background.draw(canvas, ripplePaint);
-        }
-
-        // Always restore the translation.
-        if (restoreTranslate >= 0) {
-            canvas.restoreToCount(restoreTranslate);
-        }
-
-        // If we created a layer with no content, merge it immediately.
-        if (restoreToCount >= 0 && !drewRipples) {
-            canvas.restoreToCount(restoreToCount);
-            restoreToCount = -1;
-        }
-
-        return restoreToCount;
+        return saveCount;
     }
 
     private int drawRippleLayer(Canvas canvas, Rect bounds, PorterDuffXfermode mode) {
-        // Separate the ripple color and alpha channel. The alpha will be
-        // applied when we merge the ripples down to the canvas.
-        final int rippleARGB;
-        if (mState.mColor != null) {
-            rippleARGB = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
-        } else {
-            rippleARGB = Color.TRANSPARENT;
-        }
-
-        if (mRipplePaint == null) {
-            mRipplePaint = new Paint();
-            mRipplePaint.setAntiAlias(true);
-        }
-
-        final int rippleAlpha = Color.alpha(rippleARGB);
-        final Paint ripplePaint = mRipplePaint;
-        ripplePaint.setColor(rippleARGB);
-        ripplePaint.setAlpha(0xFF);
-
         boolean drewRipples = false;
         int restoreToCount = -1;
         int restoreTranslate = -1;
@@ -807,16 +756,21 @@
             // first. This will merge SRC_OVER (directly) onto the canvas.
             if (restoreToCount < 0) {
                 final Paint maskingPaint = getMaskingPaint(mode);
-                maskingPaint.setAlpha(rippleAlpha);
+                final int color = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
+                final int alpha = Color.alpha(color);
+                maskingPaint.setAlpha(alpha / 2);
+
+                // TODO: We can avoid saveLayer here if we're only drawing one
+                // ripple and we don't have content or a translucent mask.
                 restoreToCount = canvas.saveLayer(bounds.left, bounds.top,
                         bounds.right, bounds.bottom, maskingPaint);
 
-                restoreTranslate = canvas.save();
                 // Translate the canvas to the current hotspot bounds.
+                restoreTranslate = canvas.save();
                 canvas.translate(mHotspotBounds.exactCenterX(), mHotspotBounds.exactCenterY());
             }
 
-            drewRipples |= ripple.draw(canvas, ripplePaint);
+            drewRipples |= ripple.draw(canvas, getRipplePaint());
         }
 
         // Always restore the translation.
@@ -845,6 +799,14 @@
         return restoreToCount;
     }
 
+    private Paint getRipplePaint() {
+        if (mRipplePaint == null) {
+            mRipplePaint = new Paint();
+            mRipplePaint.setAntiAlias(true);
+        }
+        return mRipplePaint;
+    }
+
     private Paint getMaskingPaint(PorterDuffXfermode xfermode) {
         if (mMaskingPaint == null) {
             mMaskingPaint = new Paint();
diff --git a/libs/hwui/AnimationContext.cpp b/libs/hwui/AnimationContext.cpp
index 716dcf5..a20bdae 100644
--- a/libs/hwui/AnimationContext.cpp
+++ b/libs/hwui/AnimationContext.cpp
@@ -17,7 +17,6 @@
 
 #include "Animator.h"
 #include "RenderNode.h"
-#include "TreeInfo.h"
 #include "renderthread/TimeLord.h"
 
 namespace android {
@@ -34,7 +33,7 @@
 }
 
 void AnimationContext::destroy() {
-    startFrame();
+    startFrame(TreeInfo::MODE_RT_ONLY);
     while (mCurrentFrameAnimations.mNextHandle) {
         AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
         AnimatorManager& animators = current->mRenderNode->animators();
@@ -55,7 +54,7 @@
     handle->insertAfter(&mNextFrameAnimations);
 }
 
-void AnimationContext::startFrame() {
+void AnimationContext::startFrame(TreeInfo::TraversalMode mode) {
     LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle,
             "Missed running animations last frame!");
     AnimationHandle* head = mNextFrameAnimations.mNextHandle;
diff --git a/libs/hwui/AnimationContext.h b/libs/hwui/AnimationContext.h
index 9b3d5f4..909ed36 100644
--- a/libs/hwui/AnimationContext.h
+++ b/libs/hwui/AnimationContext.h
@@ -20,6 +20,7 @@
 #include <utils/RefBase.h>
 #include <utils/StrongPointer.h>
 
+#include "TreeInfo.h"
 #include "renderthread/TimeLord.h"
 #include "utils/Macros.h"
 
@@ -30,7 +31,6 @@
 class AnimationListener;
 class BaseRenderNodeAnimator;
 class RenderNode;
-class TreeInfo;
 
 /*
  * AnimationHandle is several classes merged into one.
@@ -90,7 +90,7 @@
 
     // Marks the start of a frame, which will update the frame time and move all
     // next frame animations into the current frame
-    ANDROID_API virtual void startFrame();
+    ANDROID_API virtual void startFrame(TreeInfo::TraversalMode mode);
 
     // Runs any animations still left in mCurrentFrameAnimations that were not run
     // as part of the standard RenderNode:prepareTree pass.
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 1ab6235..35a4a09 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -53,6 +53,10 @@
         mListener = listener;
     }
     AnimationListener* listener() { return mListener.get(); }
+    ANDROID_API void setAllowRunningAsync(bool mayRunAsync) {
+        mMayRunAsync = mayRunAsync;
+    }
+    bool mayRunAsync() { return mMayRunAsync; }
     ANDROID_API void start() { mStagingPlayState = RUNNING; onStagingPlayStateChanged(); }
     ANDROID_API void end() { mStagingPlayState = FINISHED; onStagingPlayStateChanged(); }
 
@@ -101,6 +105,7 @@
     nsecs_t mStartTime;
     nsecs_t mDuration;
     nsecs_t mStartDelay;
+    bool mMayRunAsync;
 
     sp<AnimationListener> mListener;
 
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index e06d800..c28fb88 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -90,6 +90,9 @@
             if (animator->isRunning()) {
                 mInfo.out.hasAnimations = true;
             }
+            if (CC_UNLIKELY(!animator->mayRunAsync())) {
+                mInfo.out.requiresUiRedraw = true;
+            }
         }
         return remove;
     }
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index a10e70f..254492f 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -872,6 +872,8 @@
             handler(new (alloc) DrawLayerOp(mLayer, 0, 0),
                     renderer.getSaveCount() - 1, properties().getClipToBounds());
         } else {
+            const int saveCountOffset = renderer.getSaveCount() - 1;
+            const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
             DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
             for (size_t chunkIndex = 0; chunkIndex < mDisplayListData->getChunks().size(); chunkIndex++) {
                 const DisplayListData::Chunk& chunk = mDisplayListData->getChunks()[chunkIndex];
@@ -882,8 +884,6 @@
                 issueOperationsOf3dChildren(kNegativeZChildren,
                         initialTransform, zTranslatedNodes, renderer, handler);
 
-                const int saveCountOffset = renderer.getSaveCount() - 1;
-                const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
 
                 for (int opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
                     DisplayListOp *op = mDisplayListData->displayListOps[opIndex];
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 0c8d07f..46eeb6a 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -569,6 +569,10 @@
         return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
     }
 
+    bool hasShadow() const {
+        return getZ() >= 0.0f && getOutline().getPath() != NULL;
+    }
+
 private:
     // Rendering properties
     struct PrimitiveFields {
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp
index a7c5e85..ec8307f 100644
--- a/libs/hwui/RenderState.cpp
+++ b/libs/hwui/RenderState.cpp
@@ -38,6 +38,7 @@
 }
 
 void RenderState::onGLContextDestroyed() {
+    AutoMutex _lock(mLayerLock);
     if (CC_UNLIKELY(!mActiveLayers.empty())) {
         mCaches->dumpMemoryUsage();
         for (std::set<renderthread::CanvasContext*>::iterator cit = mRegisteredContexts.begin();
@@ -51,6 +52,13 @@
             }
             context->mRootRenderNode->debugDumpLayers("  ");
         }
+
+        for (std::set<const Layer*>::iterator lit = mActiveLayers.begin();
+             lit != mActiveLayers.end(); lit++) {
+            const Layer* layer = *(lit);
+            ALOGD("Layer %p, fbo %d, buildlayered %d",
+                    layer, layer->getFbo(), layer->wasBuildLayered);
+        }
         LOG_ALWAYS_FATAL("layers have survived gl context destruction");
     }
 }
diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h
index c7ab197..74bafca 100644
--- a/libs/hwui/RenderState.h
+++ b/libs/hwui/RenderState.h
@@ -19,6 +19,7 @@
 #include <set>
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
+#include <utils/Mutex.h>
 
 #include <private/hwui/DrawGlInfo.h>
 
@@ -52,9 +53,11 @@
     void debugOverdraw(bool enable, bool clear);
 
     void registerLayer(const Layer* layer) {
+        AutoMutex _lock(mLayerLock);
         mActiveLayers.insert(layer);
     }
     void unregisterLayer(const Layer* layer) {
+        AutoMutex _lock(mLayerLock);
         mActiveLayers.erase(layer);
     }
 
@@ -83,6 +86,7 @@
     GLsizei mViewportWidth;
     GLsizei mViewportHeight;
     GLuint mFramebuffer;
+    Mutex mLayerLock;
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 4129a89..5e6796c 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -150,7 +150,7 @@
     if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) {
         info.canvasContext = this;
     }
-    mAnimationContext->startFrame();
+    mAnimationContext->startFrame(info.mode);
     mRootRenderNode->prepareTree(info);
     mAnimationContext->runRemainingAnimations(info);
 
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 308f783..9b644f4 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -530,7 +530,6 @@
         }
     }
 
-    /** @hide */
     public static final Parcelable.Creator<AudioAttributes> CREATOR
             = new Parcelable.Creator<AudioAttributes>() {
         /**
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 9ee7027..e3b8985 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -243,7 +243,7 @@
      * or unplugged.
      * An integer value of 1 indicates a plugged-in state, 0 is unplugged.
      */
-    public static final String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.audio_plug_state";
+    public static final String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.AUDIO_PLUG_STATE";
 
     /**
      * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the maximum number of channels
@@ -251,7 +251,7 @@
      * The corresponding integer value is only available when the device is plugged in (as expressed
      * by {@link #EXTRA_AUDIO_PLUG_STATE}).
      */
-    public static final String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.max_channel_count";
+    public static final String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.MAX_CHANNEL_COUNT";
 
     /**
      * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the audio encodings supported by
@@ -261,7 +261,7 @@
      * {@link AudioFormat} (for instance see {@link AudioFormat#ENCODING_PCM_16BIT}). Use
      * {@link android.content.Intent#getIntArrayExtra(String)} to retrieve the encoding values.
      */
-    public static final String EXTRA_ENCODINGS = "android.media.extra.encodings";
+    public static final String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS";
 
     /**
      * Broadcast Action: An analog audio speaker/headset plugged in or unplugged.
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
index 6f1bdef..7c0d758 100644
--- a/media/java/android/media/AudioManagerInternal.java
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -26,6 +26,10 @@
  */
 public abstract class AudioManagerInternal {
 
+    public abstract void adjustSuggestedStreamVolumeForUid(int streamType, int direction,
+            int flags,
+            String callingPackage, int uid);
+
     public abstract void adjustStreamVolumeForUid(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 1d16793..cd4f31e 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -904,6 +904,12 @@
     /** @see AudioManager#adjustVolume(int, int) */
     public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
             String callingPackage) {
+        adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
+                Binder.getCallingUid());
+    }
+
+    private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
+            String callingPackage, int uid) {
         if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream="+suggestedStreamType
                 + ", flags=" + flags);
         int streamType;
@@ -928,7 +934,7 @@
             if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
         }
 
-        adjustStreamVolume(streamType, direction, flags, callingPackage);
+        adjustStreamVolume(streamType, direction, flags, callingPackage, uid);
     }
 
     /** @see AudioManager#adjustStreamVolume(int, int, int) */
@@ -5348,6 +5354,15 @@
      * LocalServices.
      */
     final class AudioServiceInternal extends AudioManagerInternal {
+
+        @Override
+        public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
+                String callingPackage, int uid) {
+            // direction and stream type swap here because the public
+            // adjustSuggested has a different order than the other methods.
+            adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage, uid);
+        }
+
         @Override
         public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
                 String callingPackage, int uid) {
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 3e8ee93..675916b 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -1622,8 +1622,7 @@
      * @throws IllegalStateException if in the Uninitialized state.
      */
     public MediaCodecInfo getCodecInfo() {
-        return MediaCodecList.getCodecInfoAt(
-                   MediaCodecList.findCodecByName(getName()));
+        return MediaCodecList.getInfoFor(getName());
     }
 
     private native final ByteBuffer[] getBuffers(boolean input);
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 323a3e3..01f8193 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -321,6 +321,9 @@
             // check feature support
             for (Feature feat: getValidFeatures()) {
                 Integer yesNo = (Integer)map.get(MediaFormat.KEY_FEATURE_ + feat.mName);
+                if (yesNo == null) {
+                    continue;
+                }
                 if ((yesNo == 1 && !isFeatureSupported(feat.mName)) ||
                         (yesNo == 0 && isFeatureRequired(feat.mName))) {
                     return false;
@@ -414,7 +417,7 @@
          * profile} and {@code level}.  If the type, or profile-level combination
          * is not understood by the framework, it returns null.
          */
-        public static CodecCapabilities CreateFromProfileLevel(
+        public static CodecCapabilities createFromProfileLevel(
                 String mime, int profile, int level) {
             CodecProfileLevel pl = new CodecProfileLevel();
             pl.profile = profile;
@@ -470,13 +473,12 @@
                 Integer yesNo = (Integer)map.get(key);
                 if (yesNo == null) {
                     continue;
-                } else if (yesNo > 0) {
-                    mFlagsRequired |= feat.mValue;
-                    mDefaultFormat.setInteger(key, 1);
-                } else {
-                    mFlagsSupported |= feat.mValue;
-                    mDefaultFormat.setInteger(key, 1);
                 }
+                if (yesNo > 0) {
+                    mFlagsRequired |= feat.mValue;
+                }
+                mFlagsSupported |= feat.mValue;
+                mDefaultFormat.setInteger(key, 1);
                 // TODO restrict features by mFlagsVerified once all codecs reliably verify them
             }
         }
diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java
index 5084c5c..85e9b16 100644
--- a/media/java/android/media/MediaCodecList.java
+++ b/media/java/android/media/MediaCodecList.java
@@ -116,6 +116,11 @@
 
     /* package private */ static native final int findCodecByName(String codec);
 
+    /** @hide */
+    public static MediaCodecInfo getInfoFor(String codec) {
+        return sAllCodecInfos[findCodecByName(codec)];
+    }
+
     private static native final void native_init();
 
     /**
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index fbfac89..d84cf30 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -980,7 +980,7 @@
         synchronized (mInfoLock) {
             if (controller == null) {
                 if (mCurrentSession != null) {
-                    mCurrentSession.removeCallback(mSessionCb);
+                    mCurrentSession.unregisterCallback(mSessionCb);
                     mCurrentSession = null;
                     sendMsg(mEventHandler, MSG_CLIENT_CHANGE, SENDMSG_REPLACE,
                             0 /* genId */, 1 /* clearing */, null /* obj */, 0 /* delay */);
@@ -989,12 +989,12 @@
                     || !controller.getSessionToken()
                             .equals(mCurrentSession.getSessionToken())) {
                 if (mCurrentSession != null) {
-                    mCurrentSession.removeCallback(mSessionCb);
+                    mCurrentSession.unregisterCallback(mSessionCb);
                 }
                 sendMsg(mEventHandler, MSG_CLIENT_CHANGE, SENDMSG_REPLACE,
                         0 /* genId */, 0 /* clearing */, null /* obj */, 0 /* delay */);
                 mCurrentSession = controller;
-                mCurrentSession.addCallback(mSessionCb, mEventHandler);
+                mCurrentSession.registerCallback(mSessionCb, mEventHandler);
 
                 PlaybackState state = controller.getPlaybackState();
                 sendMsg(mEventHandler, MSG_NEW_PLAYBACK_STATE, SENDMSG_REPLACE,
diff --git a/media/java/android/media/browse/MediaBrowser.aidl b/media/java/android/media/browse/MediaBrowser.aidl
new file mode 100644
index 0000000..782e094
--- /dev/null
+++ b/media/java/android/media/browse/MediaBrowser.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.media.browse;
+
+parcelable MediaBrowser.MediaItem;
\ No newline at end of file
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 338c711..34713e7 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -136,7 +136,7 @@
 
         mState = CONNECT_STATE_CONNECTING;
 
-        final Intent intent = new Intent(MediaBrowserService.SERVICE_ACTION);
+        final Intent intent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
         intent.setComponent(mServiceComponent);
 
         final ServiceConnection thisConnection = mServiceConnection = new MediaServiceConnection();
@@ -544,12 +544,11 @@
 
         /**
          * Create a new MediaItem for use in browsing media.
-         *
-         * @param flags The flags for this item.
          * @param description The description of the media, which must include a
          *            media id.
+         * @param flags The flags for this item.
          */
-        public MediaItem(@Flags int flags, @NonNull MediaDescription description) {
+        public MediaItem(@NonNull MediaDescription description, @Flags int flags) {
             if (description == null) {
                 throw new IllegalArgumentException("description cannot be null");
             }
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 4d4d646..be86741 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -329,24 +329,24 @@
     }
 
     /**
-     * Adds a callback to receive updates from the Session. Updates will be
+     * Registers a callback to receive updates from the Session. Updates will be
      * posted on the caller's thread.
      *
      * @param callback The callback object, must not be null.
      */
-    public void addCallback(@NonNull Callback callback) {
-        addCallback(callback, null);
+    public void registerCallback(@NonNull Callback callback) {
+        registerCallback(callback, null);
     }
 
     /**
-     * Adds a callback to receive updates from the session. Updates will be
+     * Registers a callback to receive updates from the session. Updates will be
      * posted on the specified handler's thread.
      *
      * @param callback The callback object, must not be null.
      * @param handler The handler to post updates on. If null the callers thread
      *            will be used.
      */
-    public void addCallback(@NonNull Callback callback, @Nullable Handler handler) {
+    public void registerCallback(@NonNull Callback callback, @Nullable Handler handler) {
         if (callback == null) {
             throw new IllegalArgumentException("callback must not be null");
         }
@@ -359,12 +359,12 @@
     }
 
     /**
-     * Stop receiving updates on the specified callback. If an update has
-     * already been posted you may still receive it after calling this method.
+     * Unregisters the specified callback. If an update has already been posted
+     * you may still receive it after calling this method.
      *
      * @param callback The callback to remove.
      */
-    public void removeCallback(@NonNull Callback callback) {
+    public void unregisterCallback(@NonNull Callback callback) {
         if (callback == null) {
             throw new IllegalArgumentException("callback must not be null");
         }
@@ -495,7 +495,7 @@
 
     /**
      * Callback for receiving updates on from the session. A Callback can be
-     * registered using {@link #addCallback}
+     * registered using {@link #registerCallback}
      */
     public static abstract class Callback {
         /**
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 46b8871..704e4a1 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -102,7 +102,7 @@
     /**
      * The ID of the TV input to provide to the setup activity and settings activity.
      */
-    public static final String EXTRA_INPUT_ID = "inputId";
+    public static final String EXTRA_INPUT_ID = "android.media.tv.extra.INPUT_ID";
 
     private static SparseIntArray sHardwareTypeToTvInputType = new SparseIntArray();
 
@@ -319,9 +319,9 @@
     }
 
     /**
-     * Returns an intent to start the setup activity for this TV input service.
+     * Returns an intent to start the setup activity for this TV input.
      */
-    public Intent getIntentForSetupActivity() {
+    public Intent createSetupIntent() {
         if (!TextUtils.isEmpty(mSetupActivity)) {
             Intent intent = new Intent(Intent.ACTION_MAIN);
             intent.setClassName(mService.serviceInfo.packageName, mSetupActivity);
@@ -332,9 +332,9 @@
     }
 
     /**
-     * Returns an intent to start the settings activity for this TV input service.
+     * Returns an intent to start the settings activity for this TV input.
      */
-    public Intent getIntentForSettingsActivity() {
+    public Intent createSettingsIntent() {
         if (!TextUtils.isEmpty(mSettingsActivity)) {
             Intent intent = new Intent(Intent.ACTION_MAIN);
             intent.setClassName(mService.serviceInfo.packageName, mSettingsActivity);
@@ -532,10 +532,6 @@
                 DELIMITER_INFO_IN_ID, PREFIX_HARDWARE_DEVICE, hardwareInfo.getDeviceId());
     }
 
-    /**
-     * Used to make this class parcelable.
-     * @hide
-     */
     public static final Parcelable.Creator<TvInputInfo> CREATOR =
             new Parcelable.Creator<TvInputInfo>() {
         @Override
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index ddc383a..d2deb66 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -75,7 +75,7 @@
      * The TV input is connected.
      * <p>
      * State for {@link #getInputState} and {@link
-     * TvInputManager.TvInputListener#onInputStateChanged}.
+     * TvInputManager.TvInputCallback#onInputStateChanged}.
      * </p>
      */
     public static final int INPUT_STATE_CONNECTED = 0;
@@ -84,7 +84,7 @@
      * fully ready.
      * <p>
      * State for {@link #getInputState} and {@link
-     * TvInputManager.TvInputListener#onInputStateChanged}.
+     * TvInputManager.TvInputCallback#onInputStateChanged}.
      * </p>
      */
     public static final int INPUT_STATE_CONNECTED_STANDBY = 1;
@@ -92,7 +92,7 @@
      * The TV input is disconnected.
      * <p>
      * State for {@link #getInputState} and {@link
-     * TvInputManager.TvInputListener#onInputStateChanged}.
+     * TvInputManager.TvInputCallback#onInputStateChanged}.
      * </p>
      */
     public static final int INPUT_STATE_DISCONNECTED = 2;
@@ -102,14 +102,14 @@
      * {@link #isRatingBlocked}.
      */
     public static final String ACTION_BLOCKED_RATINGS_CHANGED =
-            "android.media.tv.TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED";
+            "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
 
     /**
      * Broadcast intent action when the parental controls enabled state changes. For use with the
      * {@link #isParentalControlsEnabled}.
      */
     public static final String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED =
-            "android.media.tv.TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED";
+            "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
 
     /**
      * Broadcast intent action used to query available content rating systems.
@@ -143,7 +143,7 @@
      * @see TvContentRating
      */
     public static final String ACTION_QUERY_CONTENT_RATING_SYSTEMS =
-            "android.media.tv.TvInputManager.ACTION_QUERY_CONTENT_RATING_SYSTEMS";
+            "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
 
     /**
      * Content rating systems metadata associated with {@link #ACTION_QUERY_CONTENT_RATING_SYSTEMS}.
@@ -153,15 +153,15 @@
      * </p>
      */
     public static final String META_DATA_CONTENT_RATING_SYSTEMS =
-            "android.media.tv.TvInputManager.META_DATA_CONTENT_RATING_SYSTEMS";
+            "android.media.tv.metadata.CONTENT_RATING_SYSTEMS";
 
     private final ITvInputManager mService;
 
     private final Object mLock = new Object();
 
     // @GuardedBy(mLock)
-    private final List<TvInputListenerRecord> mTvInputListenerRecordsList =
-            new LinkedList<TvInputListenerRecord>();
+    private final List<TvInputCallbackRecord> mCallbackRecords =
+            new LinkedList<TvInputCallbackRecord>();
 
     // A mapping from TV input ID to the state of corresponding input.
     // @GuardedBy(mLock)
@@ -177,7 +177,7 @@
 
     private final ITvInputClient mClient;
 
-    private final ITvInputManagerCallback mCallback;
+    private final ITvInputManagerCallback mManagerCallback;
 
     private final int mUserId;
 
@@ -445,9 +445,9 @@
     }
 
     /**
-     * Interface used to monitor status of the TV input.
+     * Callback used to monitor status of the TV input.
      */
-    public abstract static class TvInputListener {
+    public abstract static class TvInputCallback {
         /**
          * This is called when the state of a given TV input is changed.
          *
@@ -479,24 +479,24 @@
         }
     }
 
-    private static final class TvInputListenerRecord {
-        private final TvInputListener mListener;
+    private static final class TvInputCallbackRecord {
+        private final TvInputCallback mCallback;
         private final Handler mHandler;
 
-        public TvInputListenerRecord(TvInputListener listener, Handler handler) {
-            mListener = listener;
+        public TvInputCallbackRecord(TvInputCallback callback, Handler handler) {
+            mCallback = callback;
             mHandler = handler;
         }
 
-        public TvInputListener getListener() {
-            return mListener;
+        public TvInputCallback getCallback() {
+            return mCallback;
         }
 
         public void postInputStateChanged(final String inputId, final int state) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    mListener.onInputStateChanged(inputId, state);
+                    mCallback.onInputStateChanged(inputId, state);
                 }
             });
         }
@@ -505,7 +505,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    mListener.onInputAdded(inputId);
+                    mCallback.onInputAdded(inputId);
                 }
             });
         }
@@ -514,7 +514,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    mListener.onInputRemoved(inputId);
+                    mCallback.onInputRemoved(inputId);
                 }
             });
         }
@@ -677,12 +677,12 @@
                 }
             }
         };
-        mCallback = new ITvInputManagerCallback.Stub() {
+        mManagerCallback = new ITvInputManagerCallback.Stub() {
             @Override
             public void onInputStateChanged(String inputId, int state) {
                 synchronized (mLock) {
                     mStateMap.put(inputId, state);
-                    for (TvInputListenerRecord record : mTvInputListenerRecordsList) {
+                    for (TvInputCallbackRecord record : mCallbackRecords) {
                         record.postInputStateChanged(inputId, state);
                     }
                 }
@@ -692,7 +692,7 @@
             public void onInputAdded(String inputId) {
                 synchronized (mLock) {
                     mStateMap.put(inputId, INPUT_STATE_CONNECTED);
-                    for (TvInputListenerRecord record : mTvInputListenerRecordsList) {
+                    for (TvInputCallbackRecord record : mCallbackRecords) {
                         record.postInputAdded(inputId);
                     }
                 }
@@ -702,14 +702,14 @@
             public void onInputRemoved(String inputId) {
                 synchronized (mLock) {
                     mStateMap.remove(inputId);
-                    for (TvInputListenerRecord record : mTvInputListenerRecordsList) {
+                    for (TvInputCallbackRecord record : mCallbackRecords) {
                         record.postInputRemoved(inputId);
                     }
                 }
             }
         };
         try {
-            mService.registerCallback(mCallback, mUserId);
+            mService.registerCallback(mManagerCallback, mUserId);
         } catch (RemoteException e) {
             Log.e(TAG, "mService.registerCallback failed: " + e);
         }
@@ -771,39 +771,39 @@
     }
 
     /**
-     * Registers a {@link TvInputListener}.
+     * Registers a {@link TvInputCallback}.
      *
-     * @param listener A listener used to monitor status of the TV inputs.
+     * @param callback A callback used to monitor status of the TV inputs.
      * @param handler A {@link Handler} that the status change will be delivered to.
      * @throws IllegalArgumentException if any of the arguments is {@code null}.
      */
-    public void registerListener(TvInputListener listener, Handler handler) {
-        if (listener == null) {
+    public void registerCallback(TvInputCallback callback, Handler handler) {
+        if (callback == null) {
             throw new IllegalArgumentException("callback cannot be null");
         }
         if (handler == null) {
             throw new IllegalArgumentException("handler cannot be null");
         }
         synchronized (mLock) {
-            mTvInputListenerRecordsList.add(new TvInputListenerRecord(listener, handler));
+            mCallbackRecords.add(new TvInputCallbackRecord(callback, handler));
         }
     }
 
     /**
-     * Unregisters the existing {@link TvInputListener}.
+     * Unregisters the existing {@link TvInputCallback}.
      *
-     * @param listener The existing listener to remove.
+     * @param callback The existing callback to remove.
      * @throws IllegalArgumentException if any of the arguments is {@code null}.
      */
-    public void unregisterListener(final TvInputListener listener) {
-        if (listener == null) {
+    public void unregisterCallback(final TvInputCallback callback) {
+        if (callback == null) {
             throw new IllegalArgumentException("callback cannot be null");
         }
         synchronized (mLock) {
-            for (Iterator<TvInputListenerRecord> it = mTvInputListenerRecordsList.iterator();
+            for (Iterator<TvInputCallbackRecord> it = mCallbackRecords.iterator();
                     it.hasNext(); ) {
-                TvInputListenerRecord record = it.next();
-                if (record.getListener() == listener) {
+                TvInputCallbackRecord record = it.next();
+                if (record.getCallback() == callback) {
                     it.remove();
                     break;
                 }
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 72a6f88..317d472 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -389,8 +389,11 @@
         }
 
         /**
-         * Informs the application that video is available and the playback of the TV stream has
-         * been started.
+         * Informs the application that the video is now available for watching. This is primarily
+         * used to signal the application to unblock the screen. The TV input service must call this
+         * method as soon as the content rendered onto its surface gets ready for viewing.
+         *
+         * @see #notifyVideoUnavailable
          */
         public void notifyVideoAvailable() {
             runOnMainThread(new Runnable() {
@@ -407,16 +410,18 @@
         }
 
         /**
-         * Informs the application that video is not available, so the TV input cannot continue
-         * playing the TV stream.
+         * Informs the application that the video became unavailable for some reason. This is
+         * primarily used to signal the application to block the screen not to show any intermittent
+         * video artifacts.
          *
-         * @param reason The reason that the TV input stopped the playback:
-         * <ul>
-         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
-         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNING}
-         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
-         * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
-         * </ul>
+         * @param reason The reason why the video became unavailable:
+         *            <ul>
+         *            <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
+         *            <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNING}
+         *            <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
+         *            <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
+         *            </ul>
+         * @see #notifyVideoAvailable
          */
         public void notifyVideoUnavailable(final int reason) {
             if (reason < TvInputManager.VIDEO_UNAVAILABLE_REASON_START
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index f4c761e..4171e6d 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -83,7 +83,7 @@
     private Rect mOverlayViewFrame;
     private final TvInputManager mTvInputManager;
     private MySessionCallback mSessionCallback;
-    private TvInputListener mListener;
+    private TvInputCallback mCallback;
     private OnUnhandledInputEventListener mOnUnhandledInputEventListener;
     private boolean mHasStreamVolume;
     private float mStreamVolume;
@@ -170,13 +170,13 @@
     }
 
     /**
-     * Sets a listener for events in this TvView.
+     * Sets the callback to be invoked when an event is dispatched to this TvView.
      *
-     * @param listener The listener to be called with events. A value of {@code null} removes any
-     *         existing listener.
+     * @param callback The callback to receive events. A value of {@code null} removes any existing
+     *            callbacks.
      */
-    public void setTvInputListener(TvInputListener listener) {
-        mListener = listener;
+    public void setCallback(TvInputCallback callback) {
+        mCallback = callback;
     }
 
     /**
@@ -680,9 +680,9 @@
     }
 
     /**
-     * Interface used to receive various status updates on the {@link TvView}.
+     * Callback used to receive various status updates on the {@link TvView}.
      */
-    public abstract static class TvInputListener {
+    public abstract static class TvInputCallback {
 
         /**
          * This is invoked when an error occurred while establishing a connection to the underlying
@@ -863,8 +863,8 @@
                 }
             } else {
                 mSessionCallback = null;
-                if (mListener != null) {
-                    mListener.onConnectionFailed(mInputId);
+                if (mCallback != null) {
+                    mCallback.onConnectionFailed(mInputId);
                 }
             }
         }
@@ -878,8 +878,8 @@
             mOverlayViewFrame = null;
             mSessionCallback = null;
             mSession = null;
-            if (mListener != null) {
-                mListener.onDisconnected(mInputId);
+            if (mCallback != null) {
+                mCallback.onDisconnected(mInputId);
             }
         }
 
@@ -891,8 +891,8 @@
             if (DEBUG) {
                 Log.d(TAG, "onChannelChangedByTvInput(" + channelUri + ")");
             }
-            if (mListener != null) {
-                mListener.onChannelRetuned(mInputId, channelUri);
+            if (mCallback != null) {
+                mCallback.onChannelRetuned(mInputId, channelUri);
             }
         }
 
@@ -904,8 +904,8 @@
             if (DEBUG) {
                 Log.d(TAG, "onTracksChanged()");
             }
-            if (mListener != null) {
-                mListener.onTracksChanged(mInputId, tracks);
+            if (mCallback != null) {
+                mCallback.onTracksChanged(mInputId, tracks);
             }
         }
 
@@ -918,8 +918,8 @@
                 Log.d(TAG, "onTrackSelected()");
             }
             // TODO: Update the video size when the type is TYPE_VIDEO.
-            if (mListener != null) {
-                mListener.onTrackSelected(mInputId, type, trackId);
+            if (mCallback != null) {
+                mCallback.onTrackSelected(mInputId, type, trackId);
             }
         }
 
@@ -931,8 +931,8 @@
             if (DEBUG) {
                 Log.d(TAG, "onVideoAvailable()");
             }
-            if (mListener != null) {
-                mListener.onVideoAvailable(mInputId);
+            if (mCallback != null) {
+                mCallback.onVideoAvailable(mInputId);
             }
         }
 
@@ -944,8 +944,8 @@
             if (DEBUG) {
                 Log.d(TAG, "onVideoUnavailable(" + reason + ")");
             }
-            if (mListener != null) {
-                mListener.onVideoUnavailable(mInputId, reason);
+            if (mCallback != null) {
+                mCallback.onVideoUnavailable(mInputId, reason);
             }
         }
 
@@ -957,8 +957,8 @@
             if (DEBUG) {
                 Log.d(TAG, "onContentAllowed()");
             }
-            if (mListener != null) {
-                mListener.onContentAllowed(mInputId);
+            if (mCallback != null) {
+                mCallback.onContentAllowed(mInputId);
             }
         }
 
@@ -970,8 +970,8 @@
             if (DEBUG) {
                 Log.d(TAG, "onContentBlocked()");
             }
-            if (mListener != null) {
-                mListener.onContentBlocked(mInputId, rating);
+            if (mCallback != null) {
+                mCallback.onContentBlocked(mInputId, rating);
             }
         }
 
@@ -1000,8 +1000,8 @@
             if (DEBUG) {
                 Log.d(TAG, "onSessionEvent(" + eventType + ")");
             }
-            if (mListener != null) {
-                mListener.onEvent(mInputId, eventType, eventArgs);
+            if (mCallback != null) {
+                mCallback.onEvent(mInputId, eventType, eventArgs);
             }
         }
     }
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 317cb96..d50be42 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -51,7 +51,7 @@
  * </p>
  *
  * To extend this class, you must declare the service in your manifest file with
- * an intent filter with the {@link #SERVICE_ACTION} action.
+ * an intent filter with the {@link #SERVICE_INTERFACE} action.
  *
  * For example:
  * </p><pre>
@@ -72,7 +72,7 @@
      * The {@link Intent} that must be declared as handled by the service.
      */
     @SdkConstant(SdkConstantType.SERVICE_ACTION)
-    public static final String SERVICE_ACTION = "android.media.browse.MediaBrowserService";
+    public static final String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
 
     private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap();
     private final Handler mHandler = new Handler();
@@ -270,7 +270,7 @@
 
     @Override
     public IBinder onBind(Intent intent) {
-        if (SERVICE_ACTION.equals(intent.getAction())) {
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
             return mBinder;
         }
         return null;
diff --git a/packages/PrintSpooler/res/layout/preview_page_loading.xml b/packages/PrintSpooler/res/layout/preview_page_loading.xml
new file mode 100644
index 0000000..1af3a17
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/preview_page_loading.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_margin="36dip"
+        android:layout_gravity="center"
+        android:src="@drawable/ic_grayedout_printer"
+        android:contentDescription="@null"
+        android:scaleType="centerInside"
+        android:adjustViewBounds="true">
+    </ImageView>
+
+</FrameLayout>
diff --git a/packages/PrintSpooler/res/values-land/constants.xml b/packages/PrintSpooler/res/values-land/constants.xml
index 6cf9754b5..84fc050 100644
--- a/packages/PrintSpooler/res/values-land/constants.xml
+++ b/packages/PrintSpooler/res/values-land/constants.xml
@@ -16,7 +16,7 @@
 
 <resources>
 
-    <integer name="preview_page_per_row_count">2</integer>
+    <integer name="preview_page_per_row_count">4</integer>
 
     <integer name="print_option_column_count">3</integer>
 
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 5b7fda3..27e1d51 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -76,7 +76,6 @@
     <!-- Title for the print dialog announced to the user for accessibility. Not shown in the UI. [CHAR LIMIT=none] -->
     <string name="print_dialog">Print dialog</string>
 
-
     <!-- Template for the message that shows the current page out of the total number of pages -->
     <string name="current_page_template"><xliff:g id="current_page">%1$d</xliff:g>
         /<xliff:g id="page_count">%2$d</xliff:g></string>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index 09e8b39..1e7a011 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -317,6 +317,11 @@
         return mState == STATE_FAILED;
     }
 
+    public boolean hasLaidOutPages() {
+        return mDocumentInfo.info != null
+                && mDocumentInfo.info.getPageCount() > 0;
+    }
+
     public void clearUpdateError() {
         if (!hasUpdateError()) {
             throw new IllegalStateException("No update error to clear");
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index d949673..ce0b9b6 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -17,6 +17,9 @@
 package com.android.printspooler.ui;
 
 import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
 import android.os.ParcelFileDescriptor;
 import android.print.PageRange;
 import android.print.PrintAttributes.MediaSize;
@@ -26,12 +29,12 @@
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.util.Log;
 import android.util.SparseArray;
-import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
+import android.view.View.MeasureSpec;
 import android.widget.TextView;
 import com.android.printspooler.R;
 import com.android.printspooler.model.PageContentRepository;
@@ -48,7 +51,7 @@
  * This class represents the adapter for the pages in the print preview list.
  */
 public final class PageAdapter extends Adapter implements
-        PageContentRepository.OnMalformedPdfFileListener{
+        PageContentRepository.OnMalformedPdfFileListener {
     private static final String LOG_TAG = "PageAdapter";
 
     private static final int MAX_PREVIEW_PAGES_BATCH = 50;
@@ -86,6 +89,8 @@
     // Pages the user selected in the UI.
     private PageRange[] mSelectedPages;
 
+    private BitmapDrawable mEmptyState;
+
     private int mDocumentPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN;
     private int mSelectedPageCount;
 
@@ -257,7 +262,7 @@
         }
 
         if (updatePreviewAreaAndPageSize) {
-            updatePreviewAreaAndPageSize();
+            updatePreviewAreaPageSizeAndEmptyState();
         }
 
         if (documentChanged) {
@@ -318,12 +323,12 @@
             }
 
             // OK, there are bugs in recycler view which tries to bind views
-            // without recycling them which would give us a chane to clean up.
+            // without recycling them which would give us a chance to clean up.
             PageContentProvider boundProvider = mPageContentRepository
-                   .peekPageContentProvider(pageIndexInFile);
+                    .peekPageContentProvider(pageIndexInFile);
             if (boundProvider != null) {
                 PageContentView owner = (PageContentView) boundProvider.getOwner();
-                owner.init(null, mMediaSize, mMinMargins);
+                owner.init(null, mEmptyState, mMediaSize, mMinMargins);
                 mPageContentRepository.releasePageContentProvider(boundProvider);
             }
 
@@ -333,7 +338,7 @@
         } else {
             onSelectedPageNotInFile(pageInDocument);
         }
-        content.init(provider, mMediaSize, mMinMargins);
+        content.init(provider, mEmptyState, mMediaSize, mMinMargins);
 
         View pageSelector = page.findViewById(R.id.page_selector);
         pageSelector.setTag(myHolder);
@@ -384,7 +389,7 @@
             mSelectedPages = selectedPages;
             mSelectedPageCount = PageRangeUtils.getNormalizedPageCount(
                     mSelectedPages, mDocumentPageCount);
-            updatePreviewAreaAndPageSize();
+            updatePreviewAreaPageSizeAndEmptyState();
             notifyDataSetChanged();
         }
         return mSelectedPages;
@@ -392,12 +397,12 @@
 
     public void onPreviewAreaSizeChanged() {
         if (mMediaSize != null) {
-            updatePreviewAreaAndPageSize();
+            updatePreviewAreaPageSizeAndEmptyState();
             notifyDataSetChanged();
         }
     }
 
-    private void updatePreviewAreaAndPageSize() {
+    private void updatePreviewAreaPageSizeAndEmptyState() {
         final int availableWidth = mPreviewArea.getWidth();
         final int availableHeight = mPreviewArea.getHeight();
 
@@ -419,7 +424,7 @@
         final int pageContentDesiredHeight = (int) (((float) pageContentDesiredWidth
                 / pageAspectRatio) + 0.5f);
 
-        // If the page does not fit entirely in a vertial direction,
+        // If the page does not fit entirely in a vertical 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,
@@ -448,6 +453,23 @@
 
         mPreviewArea.setPadding(horizontalPadding, verticalPadding,
                 horizontalPadding, verticalPadding);
+
+        // Now update the empty state drawable, as it depends on the page
+        // size and is reused for all views for better performance.
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        View content = inflater.inflate(R.layout.preview_page_loading, null, false);
+        content.measure(MeasureSpec.makeMeasureSpec(mPageContentWidth, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(mPageContentHeight, MeasureSpec.EXACTLY));
+        content.layout(0, 0, content.getMeasuredWidth(), content.getMeasuredHeight());
+
+        Bitmap bitmap = Bitmap.createBitmap(mPageContentWidth, mPageContentHeight,
+                Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+        content.draw(canvas);
+
+        // Do not recycle the old bitmap if such as it may be set as an empty
+        // state to any of the page views. Just let the GC take care of it.
+        mEmptyState = new BitmapDrawable(mContext.getResources(), bitmap);
     }
 
     private PageRange[] computeSelectedPages() {
@@ -718,7 +740,7 @@
     private void recyclePageView(PageContentView page, int pageIndexInAdapter) {
         PageContentProvider provider = page.getPageContentProvider();
         if (provider != null) {
-            page.init(null, null, null);
+            page.init(null, null, null, null);
             mPageContentRepository.releasePageContentProvider(provider);
             mBoundPagesInAdapter.remove(pageIndexInAdapter);
         }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 022e0d0..535081f 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -114,14 +114,15 @@
     private static final int DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF = Integer.MAX_VALUE;
     private static final int DEST_ADAPTER_ITEM_ID_ALL_PRINTERS = Integer.MAX_VALUE - 1;
 
-    private static final int STATE_CONFIGURING = 0;
-    private static final int STATE_PRINT_CONFIRMED = 1;
-    private static final int STATE_PRINT_CANCELED = 2;
-    private static final int STATE_UPDATE_FAILED = 3;
-    private static final int STATE_CREATE_FILE_FAILED = 4;
-    private static final int STATE_PRINTER_UNAVAILABLE = 5;
-    private static final int STATE_UPDATE_SLOW = 6;
-    private static final int STATE_PRINT_COMPLETED = 7;
+    private static final int STATE_INITIALIZING = 0;
+    private static final int STATE_CONFIGURING = 1;
+    private static final int STATE_PRINT_CONFIRMED = 2;
+    private static final int STATE_PRINT_CANCELED = 3;
+    private static final int STATE_UPDATE_FAILED = 4;
+    private static final int STATE_CREATE_FILE_FAILED = 5;
+    private static final int STATE_PRINTER_UNAVAILABLE = 6;
+    private static final int STATE_UPDATE_SLOW = 7;
+    private static final int STATE_PRINT_COMPLETED = 8;
 
     private static final int UI_STATE_PREVIEW = 0;
     private static final int UI_STATE_ERROR = 1;
@@ -196,7 +197,7 @@
 
     private int mCurrentPageCount;
 
-    private int mState;
+    private int mState = STATE_INITIALIZING;
 
     private int mUiState = UI_STATE_PREVIEW;
 
@@ -290,10 +291,17 @@
         mPrintedDocument.start();
 
         ensurePreviewUiShown();
+
+        setState(STATE_CONFIGURING);
     }
 
     @Override
     public void onPause() {
+        if (mState == STATE_INITIALIZING) {
+            super.onPause();
+            return;
+        }
+
         if (isFinishing()) {
             PrintSpoolerService spooler = mSpoolerProvider.getSpooler();
             spooler.updatePrintJobUserConfigurableOptionsNoPersistence(mPrintJob);
@@ -341,9 +349,13 @@
 
     @Override
     public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (mState == STATE_INITIALIZING) {
+            return super.onKeyUp(keyCode, event);
+        }
+
         if (keyCode == KeyEvent.KEYCODE_BACK
                 && event.isTracking() && !event.isCanceled()) {
-            if (mPrintPreviewController != null&&mPrintPreviewController.isOptionsOpened()
+            if (mPrintPreviewController != null && mPrintPreviewController.isOptionsOpened()
                     && !hasErrors()) {
                 mPrintPreviewController.closeOptions();
             } else {
@@ -900,7 +912,7 @@
         final boolean willUpdate = mPrintedDocument.update(mPrintJob.getAttributes(),
                 pages, preview);
 
-        if (willUpdate) {
+        if (willUpdate && !mPrintedDocument.hasLaidOutPages()) {
             // When the update is done we update the print preview.
             mProgressMessageController.post();
             return true;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
index 2b5b41b..a25e05e 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
@@ -195,6 +195,7 @@
         if (mPageAdapter.isOpened()) {
             mPageAdapter.close(null);
         }
+        mRecyclerView.setAdapter(null);
         mPageAdapter.destroy();
     }
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
index 23a01bd..e2ae758 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
@@ -17,17 +17,15 @@
 package com.android.printspooler.widget;
 
 import android.content.Context;
-import android.graphics.Canvas;
 import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.print.PrintAttributes.MediaSize;
 import android.print.PrintAttributes.Margins;
 import android.util.AttributeSet;
-import android.util.TypedValue;
 import android.view.View;
 import com.android.printspooler.model.PageContentRepository;
-import com.android.printspooler.model.PageContentRepository.PageContentProvider;
 import com.android.printspooler.model.PageContentRepository.RenderSpec;
+import com.android.printspooler.model.PageContentRepository.PageContentProvider;
 
 /**
  * This class represents a page in the print preview list. The width of the page
@@ -37,35 +35,20 @@
  */
 public class PageContentView extends View
         implements PageContentRepository.OnPageContentAvailableCallback {
-
-    private final ColorDrawable mEmptyState;
-
     private PageContentProvider mProvider;
 
     private MediaSize mMediaSize;
 
     private Margins mMinMargins;
 
+    private Drawable mEmptyState;
+
     private boolean mContentRequested;
 
     private boolean mNeedsLayout;
 
     public PageContentView(Context context, AttributeSet attrs) {
         super(context, attrs);
-
-        TypedValue typedValue = new TypedValue();
-        context.getTheme().resolveAttribute(com.android.internal.R.attr.textColorPrimary,
-                typedValue, true);
-
-        mEmptyState = new ColorDrawable(typedValue.data);
-
-        setBackground(mEmptyState);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        requestPageContentIfNeeded();
     }
 
     @Override
@@ -85,15 +68,19 @@
         return mProvider;
     }
 
-    public void init(PageContentProvider provider, MediaSize mediaSize, Margins minMargins) {
+    public void init(PageContentProvider provider, Drawable emptyState,
+            MediaSize mediaSize, Margins minMargins) {
         final boolean providerChanged = (mProvider == null)
                 ? provider != null : !mProvider.equals(provider);
+        final boolean loadingDrawableChanged = (mEmptyState == null)
+                ? mEmptyState != null : !mEmptyState.equals(emptyState);
         final boolean mediaSizeChanged = (mMediaSize == null)
                 ? mediaSize != null : !mMediaSize.equals(mediaSize);
         final boolean marginsChanged = (mMinMargins == null)
                 ? minMargins != null : !mMinMargins.equals(minMargins);
 
-        if (!providerChanged && !mediaSizeChanged && !marginsChanged) {
+        if (!providerChanged && !mediaSizeChanged
+                && !marginsChanged && !loadingDrawableChanged) {
             return;
         }
 
@@ -101,6 +88,7 @@
         mMediaSize = mediaSize;
         mMinMargins = minMargins;
 
+        mEmptyState = emptyState;
         mContentRequested = false;
         mNeedsLayout = mNeedsLayout || mediaSizeChanged || marginsChanged;
 
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index d4ebb01..b94a258 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -176,6 +176,7 @@
                 android:theme="@style/RecentsStyle"
                 android:excludeFromRecents="true"
                 android:launchMode="singleInstance"
+                android:resumeWhilePausing="true"
                 android:exported="true">
           <intent-filter>
             <action android:name="com.android.systemui.TOGGLE_RECENTS" />
@@ -196,6 +197,8 @@
                   android:label="@string/accessibility_desc_recent_apps"
                   android:launchMode="singleInstance"
                   android:excludeFromRecents="true"
+                  android:stateNotNeeded="true"
+                  android:resumeWhilePausing="true"
                   android:theme="@style/RecentsTheme">
             <intent-filter>
                 <action android:name="com.android.systemui.recents.TOGGLE_RECENTS" />
diff --git a/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml b/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml
new file mode 100644
index 0000000..7ca8c40
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2014 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="17.0dp"
+        android:height="17.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12.700000,10.000000c-0.800000,-2.300000 -3.000000,-4.000000 -5.700000,-4.000000c-3.300000,0.000000 -6.000000,2.700000 -6.000000,6.000000s2.700000,6.000000 6.000000,6.000000c2.600000,0.000000 4.800000,-1.700000 5.700000,-4.000000L17.000000,14.000000l0.000000,4.000000l4.000000,0.000000l0.000000,-4.000000l2.000000,0.000000l0.000000,-4.000000L12.700000,10.000000zM7.000000,14.000000c-1.100000,0.000000 -2.000000,-0.900000 -2.000000,-2.000000c0.000000,-1.100000 0.900000,-2.000000 2.000000,-2.000000s2.000000,0.900000 2.000000,2.000000C9.000000,13.100000 8.100000,14.000000 7.000000,14.000000z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index 347c8a9..3a8a17d 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -25,6 +25,13 @@
     android:gravity="center_vertical"
     android:orientation="horizontal"
     >
+    <ImageView
+        android:id="@+id/vpn"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:paddingEnd="6dp"
+        android:src="@drawable/stat_sys_vpn_ic"
+        />
     <FrameLayout
         android:id="@+id/wifi_combo"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 5399a39..0e18979 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -137,7 +137,7 @@
     <!-- The min animation duration for animating the task in when transitioning from home. -->
     <integer name="recents_animate_task_enter_from_home_duration">275</integer>
     <!-- The animation stagger to apply to each task animation when transitioning from home. -->
-    <integer name="recents_animate_task_enter_from_home_delay">150</integer>
+    <integer name="recents_animate_task_enter_from_home_delay">10</integer>
     <!-- The short duration when animating in/out the lock to app button. -->
     <integer name="recents_animate_lock_to_app_button_short_duration">150</integer>
     <!-- The long duration when animating in/out the lock to app button. -->
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index b7434fd..34430d9 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -203,8 +203,7 @@
         Drawable icon = getFullResIcon(td.resolveInfo, pm);
         if (td.userId != UserHandle.myUserId()) {
             // Need to badge the icon
-            icon = mContext.getPackageManager().getUserBadgedDrawableForDensity(icon,
-                    new UserHandle(td.userId), null, 0);
+            icon = mContext.getPackageManager().getUserBadgedIcon(icon, new UserHandle(td.userId));
         }
         if (DEBUG) Log.v(TAG, "Loaded bitmap for task "
                 + td + ": " + thumbnail);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 2d114c0..5fa9fa4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -16,10 +16,12 @@
 
 package com.android.systemui.recents;
 
+import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -385,9 +387,9 @@
                 toTask);
         if (toTransform != null && toTask.key != null) {
             Rect toTaskRect = toTransform.rect;
-
-            // XXX: Reduce the memory usage the to the task bar height
-            Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(),
+            int toHeaderWidth = (int) (mHeaderBar.getMeasuredWidth() * toTransform.scale);
+            int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale);
+            Bitmap thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight,
                     Bitmap.Config.ARGB_8888);
             if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
                 thumbnail.eraseColor(0xFFff0000);
@@ -401,7 +403,8 @@
 
             mStartAnimationTriggered = false;
             return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView,
-                    thumbnail, toTaskRect.left, toTaskRect.top, this);
+                    thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(),
+                    toTaskRect.height(), this);
         }
 
         // If both the screenshot and thumbnail fails, then just fall back to the default transition
@@ -562,11 +565,34 @@
     public void onAnimationStarted() {
         // Notify recents to start the enter animation
         if (!mStartAnimationTriggered) {
+            // There can be a race condition between the start animation callback and
+            // the start of the new activity (where we register the receiver that listens
+            // to this broadcast, so we add our own receiver and if that gets called, then
+            // we know the activity has not yet started and we can retry sending the broadcast.
+            BroadcastReceiver fallbackReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    if (getResultCode() == Activity.RESULT_OK) {
+                        mStartAnimationTriggered = true;
+                        return;
+                    }
+
+                    // Schedule for the broadcast to be sent again after some time
+                    mHandler.postDelayed(new Runnable() {
+                        @Override
+                        public void run() {
+                            onAnimationStarted();
+                        }
+                    }, 75);
+                }
+            };
+
+            // Send the broadcast to notify Recents that the animation has started
             Intent intent = new Intent(ACTION_START_ENTER_ANIMATION);
             intent.setPackage(mContext.getPackageName());
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
-            mStartAnimationTriggered = true;
+            mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
+                    fallbackReceiver, null, Activity.RESULT_CANCELED, null, null);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index ec7799a..8f92027 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -146,6 +146,9 @@
                 ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null);
                 mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
                 onEnterAnimationTriggered();
+                // Notify the fallback receiver that we have successfully got the broadcast
+                // See AlternateRecentsComponent.onAnimationStarted()
+                setResultCode(Activity.RESULT_OK);
             }
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 07a42bd..887cbac 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -356,7 +356,7 @@
      */
     public Drawable getBadgedIcon(Drawable icon, int userId) {
         if (userId != UserHandle.myUserId()) {
-            icon = mPm.getUserBadgedDrawableForDensity(icon, new UserHandle(userId), null, 0);
+            icon = mPm.getUserBadgedIcon(icon, new UserHandle(userId));
         }
         return icon;
     }
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 0c6e7b6..1bfb41f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -413,10 +413,8 @@
         final SystemServicesProxy ssp =
                 RecentsTaskLoader.getInstance().getSystemServicesProxy();
         ActivityOptions opts = null;
-        int thumbnailWidth = transform.rect.width();
-        int thumbnailHeight = transform.rect.height();
-        if (task.thumbnail != null && thumbnailWidth > 0 && thumbnailHeight > 0 &&
-                task.thumbnail.getWidth() > 0 && task.thumbnail.getHeight() > 0) {
+        if (task.thumbnail != null && task.thumbnail.getWidth() > 0 &&
+                task.thumbnail.getHeight() > 0) {
             Bitmap b;
             if (tv != null) {
                 // Disable any focused state before we draw the header
@@ -424,7 +422,11 @@
                     tv.unsetFocusedTask();
                 }
 
-                b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ARGB_8888);
+                float scale = tv.getScaleX();
+                int fromHeaderWidth = (int) (tv.mHeaderView.getMeasuredWidth() * scale);
+                int fromHeaderHeight = (int) (tv.mHeaderView.getMeasuredHeight() * scale);
+                b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight,
+                        Bitmap.Config.ARGB_8888);
                 if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
                     b.eraseColor(0xFFff0000);
                 } else {
@@ -435,7 +437,7 @@
                 }
             } else {
                 // Notify the system to skip the thumbnail layer by using an ALPHA_8 bitmap
-                b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ALPHA_8);
+                b = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
             }
             ActivityOptions.OnAnimationStartedListener animStartedListener = null;
             if (lockToTask) {
@@ -456,7 +458,8 @@
                 };
             }
             opts = ActivityOptions.makeThumbnailAspectScaleUpAnimation(sourceView,
-                    b, offsetX, offsetY, animStartedListener);
+                    b, offsetX, offsetY, transform.rect.width(), transform.rect.height(),
+                    animStartedListener);
         }
 
         final ActivityOptions launchOpts = opts;
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 eecc170..49aa52b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -839,25 +839,28 @@
 
     @Override
      public void onClick(final View v) {
-        // We purposely post the handler delayed to allow for the touch feedback to draw
         final TaskView tv = this;
-        postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                if (Constants.DebugFlags.App.EnableTaskFiltering && v == mHeaderView.mApplicationIcon) {
-                    mCb.onTaskViewAppIconClicked(tv);
-                } else if (v == mHeaderView.mDismissButton) {
-                    dismissTask();
-                } else {
-                    if (v == mActionButtonView) {
-                        // Reset the translation of the action button before we animate it out
-                        mActionButtonView.setTranslationZ(0f);
+        final boolean delayViewClick = (v != this);
+        if (delayViewClick) {
+            // We purposely post the handler delayed to allow for the touch feedback to draw
+            postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    if (Constants.DebugFlags.App.EnableTaskFiltering && v == mHeaderView.mApplicationIcon) {
+                        mCb.onTaskViewAppIconClicked(tv);
+                    } else if (v == mHeaderView.mDismissButton) {
+                        dismissTask();
                     }
-                    mCb.onTaskViewClicked(tv, tv.getTask(),
-                            (v == mFooterView || v == mActionButtonView));
                 }
+            }, 125);
+        } else {
+            if (v == mActionButtonView) {
+                // Reset the translation of the action button before we animate it out
+                mActionButtonView.setTranslationZ(0f);
             }
-        }, 125);
+            mCb.onTaskViewClicked(tv, tv.getTask(),
+                    (v == mFooterView || v == mActionButtonView));
+        }
     }
 
     /**** View.OnLongClickListener Implementation ****/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 5883c26..740211f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -27,17 +27,21 @@
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl;
+import com.android.systemui.statusbar.policy.SecurityController;
 
 // Intimately tied to the design of res/layout/signal_cluster_view.xml
 public class SignalClusterView
         extends LinearLayout
-        implements NetworkControllerImpl.SignalCluster {
+        implements NetworkControllerImpl.SignalCluster,
+        SecurityController.SecurityControllerCallback {
 
     static final String TAG = "SignalClusterView";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     NetworkControllerImpl mNC;
+    SecurityController mSC;
 
+    private boolean mVpnVisible = false;
     private boolean mWifiVisible = false;
     private int mWifiStrengthId = 0;
     private boolean mMobileVisible = false;
@@ -48,7 +52,7 @@
     private boolean mRoaming;
 
     ViewGroup mWifiGroup, mMobileGroup;
-    ImageView mWifi, mMobile, mMobileType, mAirplane;
+    ImageView mVpn, mWifi, mMobile, mMobileType, mAirplane;
     View mWifiAirplaneSpacer;
 
     public SignalClusterView(Context context) {
@@ -68,10 +72,18 @@
         mNC = nc;
     }
 
+    public void setSecurityController(SecurityController sc) {
+        if (DEBUG) Log.d(TAG, "SecurityController=" + sc);
+        mSC = sc;
+        mSC.addCallback(this);
+        mVpnVisible = mSC.isVpnEnabled();
+    }
+
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
 
+        mVpn            = (ImageView) findViewById(R.id.vpn);
         mWifiGroup      = (ViewGroup) findViewById(R.id.wifi_combo);
         mWifi           = (ImageView) findViewById(R.id.wifi_signal);
         mMobileGroup    = (ViewGroup) findViewById(R.id.mobile_combo);
@@ -85,6 +97,7 @@
 
     @Override
     protected void onDetachedFromWindow() {
+        mVpn            = null;
         mWifiGroup      = null;
         mWifi           = null;
         mMobileGroup    = null;
@@ -95,6 +108,18 @@
         super.onDetachedFromWindow();
     }
 
+    // From SecurityController.
+    @Override
+    public void onStateChanged() {
+        post(new Runnable() {
+            @Override
+            public void run() {
+                mVpnVisible = mSC.isVpnEnabled();
+                apply();
+            }
+        });
+    }
+
     @Override
     public void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription) {
         mWifiVisible = visible;
@@ -168,6 +193,8 @@
     private void apply() {
         if (mWifiGroup == null) return;
 
+        mVpn.setVisibility(mVpnVisible ? View.VISIBLE : View.GONE);
+        if (DEBUG) Log.d(TAG, String.format("vpn: %s", mVpnVisible ? "VISIBLE" : "GONE"));
         if (mWifiVisible) {
             mWifi.setImageResource(mWifiStrengthId);
             mWifiGroup.setContentDescription(mWifiDescription);
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 271371a..8497d8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -786,8 +786,11 @@
         mNetworkController.addSignalCluster(signalCluster);
         mNetworkController.addSignalCluster(signalClusterKeyguard);
         mNetworkController.addSignalCluster(signalClusterQs);
+        signalCluster.setSecurityController(mSecurityController);
         signalCluster.setNetworkController(mNetworkController);
+        signalClusterKeyguard.setSecurityController(mSecurityController);
         signalClusterKeyguard.setNetworkController(mNetworkController);
+        signalClusterQs.setSecurityController(mSecurityController);
         signalClusterQs.setNetworkController(mNetworkController);
         final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
         if (isAPhone) {
@@ -1743,12 +1746,12 @@
                     // something old was playing
                     Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: "
                             + mMediaController);
-                    mMediaController.removeCallback(mMediaListener);
+                    mMediaController.unregisterCallback(mMediaListener);
                 }
                 mMediaController = controller;
 
                 if (mMediaController != null) {
-                    mMediaController.addCallback(mMediaListener);
+                    mMediaController.registerCallback(mMediaListener);
                     mMediaMetadata = mMediaController.getMetadata();
                     if (DEBUG_MEDIA) {
                         Log.v(TAG, "DEBUG_MEDIA: insert listener, receive metadata: "
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
index 562f550..3f5cf3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
@@ -85,12 +85,12 @@
     private KeyguardBottomAreaView mKeyguardBottomArea;
 
     private CameraManager mCameraManager;
-    private CameraAvailabilityListener mCameraAvailabilityListener;
+    private CameraAvailabilityCallback mCameraAvailabilityCallback;
     private Map<String, Boolean> mCameraAvailabilityMap;
     private boolean mWaitingToLaunchSecureCamera;
     private Runnable mLaunchCameraRunnable;
 
-    private class CameraAvailabilityListener extends CameraManager.AvailabilityListener {
+    private class CameraAvailabilityCallback extends CameraManager.AvailabilityCallback {
         @Override
         public void onCameraUnavailable(String cameraId) {
             if (DEBUG) Log.d(TAG, "onCameraUnavailble(" + cameraId + ")");
@@ -123,10 +123,10 @@
         mKeyguardBottomArea = keyguardBottomArea;
 
         mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
-        mCameraAvailabilityListener = new CameraAvailabilityListener();
+        mCameraAvailabilityCallback = new CameraAvailabilityCallback();
 
         // An onCameraAvailable() or onCameraUnavailable() callback will be received for each camera
-        // when the availability listener is registered, thus initializing the map.
+        // when the availability callback is registered, thus initializing the map.
         //
         // Keeping track of the state of all cameras using the onCameraAvailable() and
         // onCameraUnavailable() callbacks can get messy when dealing with hot-pluggable cameras.
@@ -150,14 +150,14 @@
      * Initializes the SecureCameraManager and starts listening for camera availability.
      */
     public void create() {
-        mCameraManager.addAvailabilityListener(mCameraAvailabilityListener, mHandler);
+        mCameraManager.registerAvailabilityCallback(mCameraAvailabilityCallback, mHandler);
     }
 
     /**
      * Stops listening for camera availability and cleans up the SecureCameraManager.
      */
     public void destroy() {
-        mCameraManager.removeAvailabilityListener(mCameraAvailabilityListener);
+        mCameraManager.unregisterAvailabilityCallback(mCameraAvailabilityCallback);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index 70eaa5c..6f021ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -81,7 +81,7 @@
 
         if (mCameraId != null) {
             ensureHandler();
-            mCameraManager.addAvailabilityListener(mAvailabilityListener, mHandler);
+            mCameraManager.registerAvailabilityCallback(mAvailabilityCallback, mHandler);
         }
     }
 
@@ -339,8 +339,8 @@
         }
     };
 
-    private final CameraManager.AvailabilityListener mAvailabilityListener =
-            new CameraManager.AvailabilityListener() {
+    private final CameraManager.AvailabilityCallback mAvailabilityCallback =
+            new CameraManager.AvailabilityCallback() {
         @Override
         public void onCameraAvailable(String cameraId) {
             if (DEBUG) Log.d(TAG, "onCameraAvailable(" + cameraId + ")");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index a15ddaf..2fbb812 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -139,14 +139,14 @@
     }
 
     @Override
-    public void addCallback(SecurityControllerCallback callback) {
+    public void removeCallback(SecurityControllerCallback callback) {
         if (callback == null) return;
         if (DEBUG) Log.d(TAG, "removeCallback " + callback);
         mCallbacks.remove(callback);
     }
 
     @Override
-    public void removeCallback(SecurityControllerCallback callback) {
+    public void addCallback(SecurityControllerCallback callback) {
         if (callback == null || mCallbacks.contains(callback)) return;
         if (DEBUG) Log.d(TAG, "addCallback " + callback);
         mCallbacks.add(callback);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 5da8681..ffc10a9 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -1055,11 +1055,11 @@
         if (sc != null) {
             if (streamType == STREAM_REMOTE_MUSIC && controller != sc.controller) {
                 if (sc.controller != null) {
-                    sc.controller.removeCallback(mMediaControllerCb);
+                    sc.controller.unregisterCallback(mMediaControllerCb);
                 }
                 sc.controller = controller;
                 if (controller != null) {
-                    sc.controller.addCallback(mMediaControllerCb);
+                    sc.controller.registerCallback(mMediaControllerCb);
                 }
             }
             if (sc.seekbarView.getMax() != max) {
@@ -1175,7 +1175,7 @@
             StreamControl sc = mStreamControls.get(STREAM_REMOTE_MUSIC);
             if (sc != null) {
                 if (sc.controller != null) {
-                    sc.controller.removeCallback(mMediaControllerCb);
+                    sc.controller.unregisterCallback(mMediaControllerCb);
                     sc.controller = null;
                 }
             }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index e8dc800..cd3eab5 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2409,7 +2409,7 @@
             if (down) {
                 mPendingMetaAction = true;
             } else if (mPendingMetaAction) {
-                launchAssistAction();
+                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD);
             }
             return -1;
         }
@@ -2629,10 +2629,17 @@
     }
 
     private void launchAssistAction() {
+        launchAssistAction(null);
+    }
+
+    private void launchAssistAction(String hint) {
         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
         Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
                 .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
         if (intent != null) {
+            if (hint != null) {
+                intent.putExtra(hint, true);
+            }
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                     | Intent.FLAG_ACTIVITY_SINGLE_TOP
                     | Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -4233,8 +4240,12 @@
         int result;
         boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
                 || event.isWakeKey();
-        if (interactive || (isInjected && !isWakeKey)) {
-            // When the screen is on or if the key is injected pass the key to the application.
+        if (interactive
+                || (isInjected && !isWakeKey)
+                || (!interactive && shouldDispatchInputWhenNonInteractive())) {
+            // When the device is interactive, the key is injected, or we're currently dozing in a
+            // non-interactive state with the screen on and the keyguard showing,  pass the key to
+            // the application.
             result = ACTION_PASS_TO_USER;
             isWakeKey = false;
         } else {
@@ -4541,14 +4552,22 @@
 
     /** {@inheritDoc} */
     @Override
-    public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
-        // We already know this is a wake motion so just wake up.
-        // Note that we would observe policyFlags containing
-        // FLAG_WAKE and FLAG_INTERACTIVE here.
-        mPowerManager.wakeUp(whenNanos / 1000000);
+    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
+        if ((policyFlags & FLAG_WAKE) != 0) {
+            mPowerManager.wakeUp(whenNanos / 1000000);
+            return 0;
+        }
+        if (shouldDispatchInputWhenNonInteractive()) {
+            return ACTION_PASS_TO_USER;
+        }
         return 0;
     }
 
+    private boolean shouldDispatchInputWhenNonInteractive() {
+        return keyguardIsShowingTq() && mDisplay != null &&
+                mDisplay.getState() != Display.STATE_OFF;
+    }
+
     void dispatchMediaKeyWithWakeLock(KeyEvent event) {
         if (DEBUG_INPUT) {
             Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
diff --git a/services/core/java/com/android/server/NativeDaemonEvent.java b/services/core/java/com/android/server/NativeDaemonEvent.java
index 2095152..59d50bd 100644
--- a/services/core/java/com/android/server/NativeDaemonEvent.java
+++ b/services/core/java/com/android/server/NativeDaemonEvent.java
@@ -201,20 +201,16 @@
         }
         while (current < length) {
             // find the end of the word
-            if (quoted) {
-                wordEnd = current;
-                while ((wordEnd = rawEvent.indexOf('\"', wordEnd)) != -1) {
-                    if (rawEvent.charAt(wordEnd - 1) != '\\') {
-                        break;
-                    } else {
-                        wordEnd++; // skip this escaped quote and keep looking
-                    }
+            char terminator = quoted ? '\"' : ' ';
+            wordEnd = current;
+            while (wordEnd < length && rawEvent.charAt(wordEnd) != terminator) {
+                if (rawEvent.charAt(wordEnd) == '\\') {
+                    // skip the escaped char
+                    ++wordEnd;
                 }
-            } else {
-                wordEnd = rawEvent.indexOf(' ', current);
+                ++wordEnd;
             }
-            // if we didn't find the end-o-word token, take the rest of the string
-            if (wordEnd == -1) wordEnd = length;
+            if (wordEnd > length) wordEnd = length;
             String word = rawEvent.substring(current, wordEnd);
             current += word.length();
             if (!quoted) {
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index cf7e65c..cb1748d 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -397,8 +397,7 @@
                         break;
                     case NsdManager.NATIVE_DAEMON_EVENT:
                         NativeEvent event = (NativeEvent) msg.obj;
-                        if (!handleNativeEvent(event.code, event.raw,
-                                NativeDaemonEvent.unescapeArgs(event.raw))) {
+                        if (!handleNativeEvent(event.code, event.raw, event.cooked)) {
                             result = NOT_HANDLED;
                         }
                         break;
@@ -474,8 +473,14 @@
                     case NativeResponseCode.SERVICE_RESOLVED:
                         /* NNN resolveId fullName hostName port txtlen txtdata */
                         if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw);
-                        int index = cooked[2].indexOf(".");
-                        if (index == -1) {
+                        int index = 0;
+                        while (index < cooked[2].length() && cooked[2].charAt(index) != '.') {
+                            if (cooked[2].charAt(index) == '\\') {
+                                ++index;
+                            }
+                            ++index;
+                        }
+                        if (index >= cooked[2].length()) {
                             Slog.e(TAG, "Invalid service found " + raw);
                             break;
                         }
@@ -483,6 +488,8 @@
                         String rest = cooked[2].substring(index);
                         String type = rest.replace(".local.", "");
 
+                        name = unescape(name);
+
                         clientInfo.mResolvedService.setServiceName(name);
                         clientInfo.mResolvedService.setServiceType(type);
                         clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4]));
@@ -541,6 +548,30 @@
        }
     }
 
+    private String unescape(String s) {
+        StringBuilder sb = new StringBuilder(s.length());
+        for (int i = 0; i < s.length(); ++i) {
+            char c = s.charAt(i);
+            if (c == '\\') {
+                if (++i >= s.length()) {
+                    Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
+                    break;
+                }
+                c = s.charAt(i);
+                if (c != '.' && c != '\\') {
+                    if (i + 2 >= s.length()) {
+                        Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
+                        break;
+                    }
+                    c = (char) ((c-'0') * 100 + (s.charAt(i+1)-'0') * 10 + (s.charAt(i+2)-'0'));
+                    i += 2;
+                }
+            }
+            sb.append(c);
+        }
+        return sb.toString();
+    }
+
     private NativeDaemonConnector mNativeConnector;
     private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1);
 
@@ -625,10 +656,12 @@
     private class NativeEvent {
         final int code;
         final String raw;
+        final String[] cooked;
 
-        NativeEvent(int code, String raw) {
+        NativeEvent(int code, String raw, String[] cooked) {
             this.code = code;
             this.raw = raw;
+            this.cooked = cooked;
         }
     }
 
@@ -644,7 +677,7 @@
         public boolean onEvent(int code, String raw, String[] cooked) {
             // TODO: NDC translates a message to a callback, we could enhance NDC to
             // directly interact with a state machine through messages
-            NativeEvent event = new NativeEvent(code, raw);
+            NativeEvent event = new NativeEvent(code, raw, cooked);
             mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event);
             return true;
         }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index c469b42..888fa1a 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -265,7 +265,11 @@
         mContext.registerReceiver(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context1, Intent intent) {
-                purgeOldGrantsAll();
+                // Don't delete accounts when updating a authenticator's
+                // package.
+                if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                    purgeOldGrantsAll();
+                }
             }
         }, intentFilter);
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 023f627..1397ea4 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6278,12 +6278,12 @@
     }
 
     @Override
-    public final void activityPaused(IBinder token, PersistableBundle persistentState) {
+    public final void activityPaused(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         synchronized(this) {
             ActivityStack stack = ActivityRecord.getStackLocked(token);
             if (stack != null) {
-                stack.activityPausedLocked(token, false, persistentState);
+                stack.activityPausedLocked(token, false);
             }
         }
         Binder.restoreCallingIdentity(origId);
@@ -9945,7 +9945,7 @@
     }
 
     private void updateEventDispatchingLocked() {
-        mWindowManager.setEventDispatching(mBooted && !mWentToSleep && !mShuttingDown);
+        mWindowManager.setEventDispatching(mBooted && !mShuttingDown);
     }
 
     public void setLockScreenShown(boolean shown) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 77b4cc9..e043f03 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -698,12 +698,12 @@
                 case ActivityOptions.ANIM_SCALE_UP:
                     service.mWindowManager.overridePendingAppTransitionScaleUp(
                             pendingOptions.getStartX(), pendingOptions.getStartY(),
-                            pendingOptions.getStartWidth(), pendingOptions.getStartHeight());
+                            pendingOptions.getWidth(), pendingOptions.getHeight());
                     if (intent.getSourceBounds() == null) {
                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
                                 pendingOptions.getStartY(),
-                                pendingOptions.getStartX()+pendingOptions.getStartWidth(),
-                                pendingOptions.getStartY()+pendingOptions.getStartHeight()));
+                                pendingOptions.getStartX()+pendingOptions.getWidth(),
+                                pendingOptions.getStartY()+pendingOptions.getHeight()));
                     }
                     break;
                 case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
@@ -728,15 +728,14 @@
                     service.mWindowManager.overridePendingAppTransitionAspectScaledThumb(
                             pendingOptions.getThumbnail(),
                             pendingOptions.getStartX(), pendingOptions.getStartY(),
+                            pendingOptions.getWidth(), pendingOptions.getHeight(),
                             pendingOptions.getOnAnimationStartListener(),
                             (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP));
                     if (intent.getSourceBounds() == null) {
                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
                                 pendingOptions.getStartY(),
-                                pendingOptions.getStartX()
-                                        + pendingOptions.getThumbnail().getWidth(),
-                                pendingOptions.getStartY()
-                                        + pendingOptions.getThumbnail().getHeight()));
+                                pendingOptions.getStartX() + pendingOptions.getWidth(),
+                                pendingOptions.getStartY() + pendingOptions.getHeight()));
                     }
                     break;
                 default:
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 81c379a..bcf3b17 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -284,7 +284,7 @@
                         if (r.app != null) {
                             mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
                         }
-                        activityPausedLocked(r.appToken, true, r.persistentState);
+                        activityPausedLocked(r.appToken, true);
                     }
                 } break;
                 case LAUNCH_TICK_MSG: {
@@ -425,13 +425,13 @@
     }
 
     final ActivityRecord topActivity() {
-        // Iterate to find the first non-empty task stack. Note that this code can
-        // be simplified once we stop storing tasks with empty mActivities lists.
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            final int topActivityNdx = activities.size() - 1;
-            if (topActivityNdx >= 0) {
-                return activities.get(topActivityNdx);
+            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = activities.get(activityNdx);
+                if (!r.finishing) {
+                    return r;
+                }
             }
         }
         return null;
@@ -712,7 +712,7 @@
             // Still have something resumed; can't sleep until it is paused.
             if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause " + mResumedActivity);
             if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
-            startPausingLocked(false, true);
+            startPausingLocked(false, true, false, false);
             return true;
         }
         if (mPausingActivity != null) {
@@ -790,22 +790,38 @@
         return null;
     }
 
-    final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
+    /**
+     * Start pausing the currently resumed activity.  It is an error to call this if there
+     * is already an activity being paused or there is no resumed activity.
+     *
+     * @param userLeaving True if this should result in an onUserLeaving to the current activity.
+     * @param uiSleeping True if this is happening with the user interface going to sleep (the
+     * screen turning off).
+     * @param resuming True if this is being called as part of resuming the top activity, so
+     * we shouldn't try to instigate a resume here.
+     * @param dontWait True if the caller does not want to wait for the pause to complete.  If
+     * set to true, we will immediately complete the pause here before returning.
+     * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
+     * it to tell us when it is done.
+     */
+    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
+            boolean dontWait) {
         if (mPausingActivity != null) {
-            Slog.e(TAG, "Trying to pause when pause is already pending for "
-                  + mPausingActivity, new RuntimeException("here").fillInStackTrace());
+            Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity);
+            completePauseLocked(false);
         }
         ActivityRecord prev = mResumedActivity;
         if (prev == null) {
-            Slog.e(TAG, "Trying to pause when nothing is resumed",
-                    new RuntimeException("here").fillInStackTrace());
-            mStackSupervisor.resumeTopActivitiesLocked();
-            return;
+            if (!resuming) {
+                Slog.wtf(TAG, "Trying to pause when nothing is resumed");
+                mStackSupervisor.resumeTopActivitiesLocked();
+            }
+            return false;
         }
 
         if (mActivityContainer.mParentActivity == null) {
             // Top level stack, not a child. Look for child stacks.
-            mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping);
+            mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping, resuming, dontWait);
         }
 
         if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
@@ -834,7 +850,7 @@
                         prev.shortComponentName);
                 mService.updateUsageStats(prev, false);
                 prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
-                        userLeaving, prev.configChangeFlags);
+                        userLeaving, prev.configChangeFlags, dontWait);
             } catch (Exception e) {
                 // Ignore exception, if process died other code will cleanup.
                 Slog.w(TAG, "Exception thrown during pause", e);
@@ -865,39 +881,46 @@
                 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
             }
 
-            // Schedule a pause timeout in case the app doesn't respond.
-            // We don't give it much time because this directly impacts the
-            // responsiveness seen by the user.
-            Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
-            msg.obj = prev;
-            prev.pauseTime = SystemClock.uptimeMillis();
-            mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
-            if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
+            if (dontWait) {
+                // If the caller said they don't want to wait for the pause, then complete
+                // the pause now.
+                completePauseLocked(false);
+                return false;
+
+            } else {
+                // Schedule a pause timeout in case the app doesn't respond.
+                // We don't give it much time because this directly impacts the
+                // responsiveness seen by the user.
+                Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
+                msg.obj = prev;
+                prev.pauseTime = SystemClock.uptimeMillis();
+                mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
+                if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
+                return true;
+            }
+
         } else {
             // This activity failed to schedule the
             // pause, so just treat it as being paused now.
             if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
-            mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
+            if (!resuming) {
+                mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
+            }
+            return false;
         }
     }
 
-    final void activityPausedLocked(IBinder token, boolean timeout,
-            PersistableBundle persistentState) {
+    final void activityPausedLocked(IBinder token, boolean timeout) {
         if (DEBUG_PAUSE) Slog.v(
             TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
 
         final ActivityRecord r = isInStackLocked(token);
         if (r != null) {
             mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
-            if (persistentState != null) {
-                r.persistentState = persistentState;
-                mService.notifyTaskPersisterLocked(r.task, false);
-            }
             if (mPausingActivity == r) {
                 if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
                         + (timeout ? " (due to timeout)" : " (pause complete)"));
-                r.state = ActivityState.PAUSED;
-                completePauseLocked();
+                completePauseLocked(true);
             } else {
                 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
                         r.userId, System.identityHashCode(r), r.shortComponentName,
@@ -948,11 +971,12 @@
         }
     }
 
-    private void completePauseLocked() {
+    private void completePauseLocked(boolean resumeNext) {
         ActivityRecord prev = mPausingActivity;
         if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
 
         if (prev != null) {
+            prev.state = ActivityState.PAUSED;
             if (prev.finishing) {
                 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
                 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
@@ -995,19 +1019,21 @@
             mPausingActivity = null;
         }
 
-        final ActivityStack topStack = mStackSupervisor.getFocusedStack();
-        if (!mService.isSleepingOrShuttingDown()) {
-            mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
-        } else {
-            mStackSupervisor.checkReadyForSleepLocked();
-            ActivityRecord top = topStack.topRunningActivityLocked(null);
-            if (top == null || (prev != null && top != prev)) {
-                // If there are no more activities available to run,
-                // do resume anyway to start something.  Also if the top
-                // activity on the stack is not the just paused activity,
-                // we need to go ahead and resume it to ensure we complete
-                // an in-flight app switch.
-                mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
+        if (resumeNext) {
+            final ActivityStack topStack = mStackSupervisor.getFocusedStack();
+            if (!mService.isSleepingOrShuttingDown()) {
+                mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
+            } else {
+                mStackSupervisor.checkReadyForSleepLocked();
+                ActivityRecord top = topStack.topRunningActivityLocked(null);
+                if (top == null || (prev != null && top != prev)) {
+                    // If there are no more activities available to run,
+                    // do resume anyway to start something.  Also if the top
+                    // activity on the stack is not the just paused activity,
+                    // we need to go ahead and resume it to ensure we complete
+                    // an in-flight app switch.
+                    mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
+                }
             }
         }
 
@@ -1607,10 +1633,10 @@
 
         // We need to start pausing the current activity so the top one
         // can be resumed...
-        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving);
+        boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
+        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
         if (mResumedActivity != null) {
-            pausing = true;
-            startPausingLocked(userLeaving, false);
+            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
         }
         if (pausing) {
@@ -2720,7 +2746,7 @@
             if (mPausingActivity == null) {
                 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
                 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
-                startPausingLocked(false, false);
+                startPausingLocked(false, false, false, false);
             }
 
             if (endTask) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 780efa1..45479e3 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -592,7 +592,7 @@
      * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
      * @return true if any activity was paused as a result of this call.
      */
-    boolean pauseBackStacks(boolean userLeaving) {
+    boolean pauseBackStacks(boolean userLeaving, boolean resuming, boolean dontWait) {
         boolean someActivityPaused = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
@@ -601,8 +601,8 @@
                 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
                     if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack +
                             " mResumedActivity=" + stack.mResumedActivity);
-                    stack.startPausingLocked(userLeaving, false);
-                    someActivityPaused = true;
+                    someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
+                            dontWait);
                 }
             }
         }
@@ -631,7 +631,8 @@
         return pausing;
     }
 
-    void pauseChildStacks(ActivityRecord parent, boolean userLeaving, boolean uiSleeping) {
+    void pauseChildStacks(ActivityRecord parent, boolean userLeaving, boolean uiSleeping,
+            boolean resuming, boolean dontWait) {
         // TODO: Put all stacks in supervisor and iterate through them instead.
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
@@ -639,7 +640,7 @@
                 final ActivityStack stack = stacks.get(stackNdx);
                 if (stack.mResumedActivity != null &&
                         stack.mActivityContainer.mParentActivity == parent) {
-                    stack.startPausingLocked(userLeaving, uiSleeping);
+                    stack.startPausingLocked(userLeaving, uiSleeping, resuming, dontWait);
                 }
             }
         }
@@ -1640,57 +1641,8 @@
             }
         }
 
-        if (sourceRecord == null) {
-            // This activity is not being started from another...  in this
-            // case we -always- start a new task.
-            if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) {
-                Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
-                        "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
-                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
-            }
-        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
-            // The original activity who is starting us is running as a single
-            // instance...  this new activity it is starting must go on its
-            // own task.
-            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
-        } else if (launchSingleInstance || launchSingleTask) {
-            // The activity being started is a single instance...  it always
-            // gets launched into its own task.
-            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
-        }
-
-        ActivityInfo newTaskInfo = null;
-        Intent newTaskIntent = null;
-        ActivityStack sourceStack;
-        if (sourceRecord != null) {
-            if (sourceRecord.finishing) {
-                // If the source is finishing, we can't further count it as our source.  This
-                // is because the task it is associated with may now be empty and on its way out,
-                // so we don't want to blindly throw it in to that task.  Instead we will take
-                // the NEW_TASK flow and try to find a task for it. But save the task information
-                // so it can be used when creating the new task.
-                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
-                    Slog.w(TAG, "startActivity called from finishing " + sourceRecord
-                            + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
-                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
-                    newTaskInfo = sourceRecord.info;
-                    newTaskIntent = sourceRecord.task.intent;
-                }
-                sourceRecord = null;
-                sourceStack = null;
-            } else {
-                sourceStack = sourceRecord.task.stack;
-            }
-        } else {
-            sourceStack = null;
-        }
-
         boolean addingToTask = false;
-        boolean movedHome = false;
         TaskRecord reuseTask = null;
-        ActivityStack targetStack;
-
-        intent.setFlags(launchFlags);
 
         // If the caller is not coming from another activity, but has given us an
         // explicit task into which they would like us to launch the new activity,
@@ -1746,6 +1698,58 @@
             inTask = null;
         }
 
+        if (inTask == null) {
+            if (sourceRecord == null) {
+                // This activity is not being started from another...  in this
+                // case we -always- start a new task.
+                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) {
+                    Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
+                            "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
+                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+                }
+            } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
+                // The original activity who is starting us is running as a single
+                // instance...  this new activity it is starting must go on its
+                // own task.
+                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+            } else if (launchSingleInstance || launchSingleTask) {
+                // The activity being started is a single instance...  it always
+                // gets launched into its own task.
+                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+            }
+        }
+
+        ActivityInfo newTaskInfo = null;
+        Intent newTaskIntent = null;
+        ActivityStack sourceStack;
+        if (sourceRecord != null) {
+            if (sourceRecord.finishing) {
+                // If the source is finishing, we can't further count it as our source.  This
+                // is because the task it is associated with may now be empty and on its way out,
+                // so we don't want to blindly throw it in to that task.  Instead we will take
+                // the NEW_TASK flow and try to find a task for it. But save the task information
+                // so it can be used when creating the new task.
+                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
+                    Slog.w(TAG, "startActivity called from finishing " + sourceRecord
+                            + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
+                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+                    newTaskInfo = sourceRecord.info;
+                    newTaskIntent = sourceRecord.task.intent;
+                }
+                sourceRecord = null;
+                sourceStack = null;
+            } else {
+                sourceStack = sourceRecord.task.stack;
+            }
+        } else {
+            sourceStack = null;
+        }
+
+        boolean movedHome = false;
+        ActivityStack targetStack;
+
+        intent.setFlags(launchFlags);
+
         // We may want to try to place the new activity in to an existing task.  We always
         // do this if the target activity is singleTask or singleInstance; we will also do
         // this if NEW_TASK has been requested, and there is not an additional qualifier telling
@@ -1768,7 +1772,7 @@
                 if (intentActivity != null) {
                     if (isLockTaskModeViolation(intentActivity.task)) {
                         showLockTaskToast();
-                        Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
+                        Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
                         return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
                     }
                     if (r.task == null) {
@@ -3840,7 +3844,7 @@
                 mContainerState = CONTAINER_STATE_NO_SURFACE;
                 ((VirtualActivityDisplay) mActivityDisplay).setSurface(null);
                 if (mStack.mPausingActivity == null && mStack.mResumedActivity != null) {
-                    mStack.startPausingLocked(false, true);
+                    mStack.startPausingLocked(false, true, false, false);
                 }
             }
 
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 9e81149..bbb8371 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -1429,8 +1429,8 @@
     }
 
     // Native callback.
-    private int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
-        return mWindowManagerCallbacks.interceptWakeMotionBeforeQueueing(
+    private int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
+        return mWindowManagerCallbacks.interceptMotionBeforeQueueingNonInteractive(
                 whenNanos, policyFlags);
     }
 
@@ -1593,7 +1593,7 @@
 
         public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
 
-        public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags);
+        public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
 
         public long interceptKeyBeforeDispatching(InputWindowHandle focus,
                 KeyEvent event, int policyFlags);
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 2ef9828..0cb8eb8 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -453,11 +453,10 @@
         @Override public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
 
+            if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
             if (action.equals(ALARM_WAKEUP)) {
-                if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
                 startNavigating(false);
             } else if (action.equals(ALARM_TIMEOUT)) {
-                if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
                 hibernate();
             } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
                 checkSmsSuplInit(intent);
@@ -691,7 +690,6 @@
         intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
-        intentFilter = new IntentFilter();
         intentFilter.addAction(SIM_STATE_CHANGED);
         mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
     }
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index b936130d..5097927 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -229,8 +229,14 @@
      * {@link AudioManager#ADJUST_SAME}.
      *
      * @param direction The direction to adjust volume in.
+     * @param flags Any of the flags from {@link AudioManager}.
+     * @param packageName The package that made the original volume request.
+     * @param uid The uid that made the original volume request.
+     * @param useSuggested True to use adjustSuggestedStreamVolume instead of
+     *            adjustStreamVolume.
      */
-    public void adjustVolume(int direction, int flags, String packageName, int uid) {
+    public void adjustVolume(int direction, int flags, String packageName, int uid,
+            boolean useSuggested) {
         if (isPlaybackActive(false) || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) {
             flags &= ~AudioManager.FLAG_PLAY_SOUND;
         }
@@ -241,8 +247,13 @@
         }
         if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
             int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
-            mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags, packageName,
-                    uid);
+            if (useSuggested) {
+                mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, direction, flags,
+                        packageName, uid);
+            } else {
+                mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
+                        packageName, uid);
+            }
         } else {
             if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
                 // Nothing to do, the volume cannot be changed
@@ -1020,7 +1031,7 @@
             int uid = Binder.getCallingUid();
             final long token = Binder.clearCallingIdentity();
             try {
-                MediaSessionRecord.this.adjustVolume(direction, flags, packageName, uid);
+                MediaSessionRecord.this.adjustVolume(direction, flags, packageName, uid, false);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 0c6d46c..a12dd1c 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -814,7 +814,7 @@
                 }
             } else {
                 session.adjustVolume(direction, flags, getContext().getPackageName(),
-                        UserHandle.myUserId());
+                        UserHandle.myUserId(), true);
                 if (session.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE
                         && mRvc != null) {
                     try {
diff --git a/services/core/java/com/android/server/notification/DowntimeConditionProvider.java b/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
index 317ebef..b71bad8 100644
--- a/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
+++ b/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
@@ -43,6 +43,7 @@
 import java.util.Date;
 import java.util.Locale;
 import java.util.Objects;
+import java.util.TimeZone;
 
 /** Built-in zen condition provider for managing downtime */
 public class DowntimeConditionProvider extends ConditionProviderService {
@@ -275,6 +276,9 @@
                 final long schTime = intent.getLongExtra(EXTRA_TIME, 0);
                 if (DEBUG) Slog.d(TAG, String.format("%s scheduled for %s, fired at %s, delta=%s",
                         action, ts(schTime), ts(now), now - schTime));
+            } else if (Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
+                if (DEBUG) Slog.d(TAG, "timezone changed to " + TimeZone.getDefault());
+                mCalendar.setTimeZone(TimeZone.getDefault());
             } else {
                 if (DEBUG) Slog.d(TAG, action + " fired at " + now);
             }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index bc538ed..54f043d 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -69,6 +69,7 @@
 import android.service.notification.IConditionListener;
 import android.service.notification.IConditionProvider;
 import android.service.notification.INotificationListener;
+import android.service.notification.IStatusBarNotificationHolder;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationRankingUpdate;
 import android.service.notification.StatusBarNotification;
@@ -2848,8 +2849,9 @@
         private void notifyPosted(final ManagedServiceInfo info,
                 final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) {
             final INotificationListener listener = (INotificationListener)info.service;
+            StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
             try {
-                listener.onNotificationPosted(sbn, rankingUpdate);
+                listener.onNotificationPosted(sbnHolder, rankingUpdate);
             } catch (RemoteException ex) {
                 Log.e(TAG, "unable to notify listener (posted): " + listener, ex);
             }
@@ -2861,8 +2863,9 @@
                 return;
             }
             final INotificationListener listener = (INotificationListener) info.service;
+            StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
             try {
-                listener.onNotificationRemoved(sbn, rankingUpdate);
+                listener.onNotificationRemoved(sbnHolder, rankingUpdate);
             } catch (RemoteException ex) {
                 Log.e(TAG, "unable to notify listener (removed): " + listener, ex);
             }
@@ -2950,4 +2953,22 @@
             return zen ? "zen" : ('\'' + pkgFilter + '\'');
         }
     }
+
+    /**
+     * Wrapper for a StatusBarNotification object that allows transfer across a oneway
+     * binder without sending large amounts of data over a oneway transaction.
+     */
+    private static final class StatusBarNotificationHolder
+            extends IStatusBarNotificationHolder.Stub {
+        private final StatusBarNotification mValue;
+
+        public StatusBarNotificationHolder(StatusBarNotification value) {
+            mValue = value;
+        }
+
+        @Override
+        public StatusBarNotification get() {
+            return mValue;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 9a00923..496c136 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -42,7 +42,6 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.IntentSender.SendIntentException;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageInstaller;
 import android.content.pm.IPackageInstallerCallback;
 import android.content.pm.IPackageInstallerSession;
@@ -50,15 +49,11 @@
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageInstaller.SessionParams;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.PackageLite;
-import android.content.pm.PackageParser.PackageParserException;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
-import android.os.Environment.UserEnvironment;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -70,7 +65,6 @@
 import android.os.SELinux;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.storage.StorageManager;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.text.TextUtils;
@@ -126,6 +120,7 @@
     private static final String ATTR_CREATED_MILLIS = "createdMillis";
     private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
     private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
+    private static final String ATTR_PREPARED = "prepared";
     private static final String ATTR_SEALED = "sealed";
     private static final String ATTR_MODE = "mode";
     private static final String ATTR_INSTALL_FLAGS = "installFlags";
@@ -148,7 +143,6 @@
     private final Context mContext;
     private final PackageManagerService mPm;
     private final AppOpsManager mAppOps;
-    private final StorageManager mStorage;
 
     private final File mStagingDir;
     private final HandlerThread mInstallThread;
@@ -190,7 +184,6 @@
         mContext = context;
         mPm = pm;
         mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
-        mStorage = StorageManager.from(mContext);
 
         mStagingDir = stagingDir;
 
@@ -266,7 +259,9 @@
             try {
                 final int sessionId = allocateSessionIdLocked();
                 mLegacySessions.put(sessionId, true);
-                return prepareInternalStageDir(sessionId);
+                final File stageDir = buildInternalStageDir(sessionId);
+                prepareInternalStageDir(stageDir);
+                return stageDir;
             } catch (IllegalStateException e) {
                 throw new IOException(e);
             }
@@ -345,6 +340,7 @@
         final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR);
         final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null;
         final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID);
+        final boolean prepared = readBooleanAttribute(in, ATTR_PREPARED, true);
         final boolean sealed = readBooleanAttribute(in, ATTR_SEALED);
 
         final SessionParams params = new SessionParams(
@@ -362,7 +358,7 @@
 
         return new PackageInstallerSession(mInternalCallback, mContext, mPm,
                 mInstallThread.getLooper(), sessionId, userId, installerPackageName, params,
-                createdMillis, stageDir, stageCid, sealed);
+                createdMillis, stageDir, stageCid, prepared, sealed);
     }
 
     private void writeSessionsLocked() {
@@ -410,6 +406,7 @@
         if (session.stageCid != null) {
             writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.stageCid);
         }
+        writeBooleanAttribute(out, ATTR_PREPARED, session.isPrepared());
         writeBooleanAttribute(out, ATTR_SEALED, session.isSealed());
 
         writeIntAttribute(out, ATTR_MODE, params.mode);
@@ -483,14 +480,10 @@
             }
         }
 
-        // TODO: treat INHERIT_EXISTING as install for user
-
-        // Figure out where we're going to be staging session data
-        final boolean stageInternal;
-
-        if (params.mode == SessionParams.MODE_FULL_INSTALL) {
-            // Brand new install, use best resolved location. This also verifies
-            // that target has enough free space for the install.
+        if (params.mode == SessionParams.MODE_FULL_INSTALL
+                || params.mode == SessionParams.MODE_INHERIT_EXISTING) {
+            // Resolve best location for install, based on combination of
+            // requested install flags, delta size, and manifest settings.
             final long ident = Binder.clearCallingIdentity();
             try {
                 final int resolved = PackageHelper.resolveInstallLocation(mContext,
@@ -498,46 +491,15 @@
                         params.installFlags);
 
                 if (resolved == PackageHelper.RECOMMEND_INSTALL_INTERNAL) {
-                    stageInternal = true;
+                    params.setInstallFlagsInternal();
                 } else if (resolved == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
-                    stageInternal = false;
+                    params.setInstallFlagsExternal();
                 } else {
                     throw new IOException("No storage with enough free space; res=" + resolved);
                 }
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
-        } else if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
-            // Inheriting existing install, so stay on the same storage medium.
-            final ApplicationInfo existingApp = mPm.getApplicationInfo(params.appPackageName, 0,
-                    userId);
-            if (existingApp == null) {
-                throw new IllegalStateException(
-                        "Missing existing app " + params.appPackageName);
-            }
-
-            final long existingSize;
-            try {
-                final PackageLite existingPkg = PackageParser.parsePackageLite(
-                        new File(existingApp.getCodePath()), 0);
-                existingSize = PackageHelper.calculateInstalledSize(existingPkg, false,
-                        params.abiOverride);
-            } catch (PackageParserException e) {
-                throw new IllegalStateException(
-                        "Failed to calculate size of " + params.appPackageName);
-            }
-
-            if ((existingApp.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0) {
-                // Internal we can link existing install into place, so we only
-                // need enough space for the new data.
-                checkInternalStorage(params.sizeBytes);
-                stageInternal = true;
-            } else {
-                // External we're going to copy existing install into our
-                // container, so we need footprint of both.
-                checkExternalStorage(params.sizeBytes + existingSize);
-                stageInternal = false;
-            }
         } else {
             throw new IllegalArgumentException("Invalid install mode: " + params.mode);
         }
@@ -563,15 +525,15 @@
             // We're staging to exactly one location
             File stageDir = null;
             String stageCid = null;
-            if (stageInternal) {
-                stageDir = prepareInternalStageDir(sessionId);
+            if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+                stageDir = buildInternalStageDir(sessionId);
             } else {
-                stageCid = prepareExternalStageCid(sessionId, params.sizeBytes);
+                stageCid = buildExternalStageCid(sessionId);
             }
 
             session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
                     mInstallThread.getLooper(), sessionId, userId, installerPackageName, params,
-                    createdMillis, stageDir, stageCid, false);
+                    createdMillis, stageDir, stageCid, false, false);
             mSessions.put(sessionId, session);
         }
 
@@ -615,32 +577,16 @@
         }
     }
 
-    private void checkInternalStorage(long sizeBytes) throws IOException {
-        if (sizeBytes <= 0) return;
-
-        final File target = Environment.getDataDirectory();
-        final long targetBytes = sizeBytes + mStorage.getStorageLowBytes(target);
-
-        mPm.freeStorage(targetBytes);
-        if (target.getUsableSpace() < targetBytes) {
-            throw new IOException("Not enough internal space to write " + sizeBytes + " bytes");
-        }
-    }
-
-    private void checkExternalStorage(long sizeBytes) throws IOException {
-        if (sizeBytes <= 0) return;
-
-        final File target = new UserEnvironment(UserHandle.USER_OWNER)
-                .getExternalStorageDirectory();
-        final long targetBytes = sizeBytes + mStorage.getStorageLowBytes(target);
-
-        if (target.getUsableSpace() < targetBytes) {
-            throw new IOException("Not enough external space to write " + sizeBytes + " bytes");
-        }
-    }
-
     @Override
     public IPackageInstallerSession openSession(int sessionId) {
+        try {
+            return openSessionInternal(sessionId);
+        } catch (IOException e) {
+            throw ExceptionUtils.wrap(e);
+        }
+    }
+
+    private IPackageInstallerSession openSessionInternal(int sessionId) throws IOException {
         synchronized (mSessions) {
             final PackageInstallerSession session = mSessions.get(sessionId);
             if (session == null || !isCallingUidOwner(session)) {
@@ -665,40 +611,37 @@
         throw new IllegalStateException("Failed to allocate session ID");
     }
 
-    private File prepareInternalStageDir(int sessionId) throws IOException {
-        final File file = new File(mStagingDir, "vmdl" + sessionId + ".tmp");
+    private File buildInternalStageDir(int sessionId) {
+        return new File(mStagingDir, "vmdl" + sessionId + ".tmp");
+    }
 
-        if (file.exists()) {
-            throw new IOException("Session dir already exists: " + file);
+    static void prepareInternalStageDir(File stageDir) throws IOException {
+        if (stageDir.exists()) {
+            throw new IOException("Session dir already exists: " + stageDir);
         }
 
         try {
-            Os.mkdir(file.getAbsolutePath(), 0755);
-            Os.chmod(file.getAbsolutePath(), 0755);
+            Os.mkdir(stageDir.getAbsolutePath(), 0755);
+            Os.chmod(stageDir.getAbsolutePath(), 0755);
         } catch (ErrnoException e) {
             // This purposefully throws if directory already exists
-            throw new IOException("Failed to prepare session dir", e);
+            throw new IOException("Failed to prepare session dir: " + stageDir, e);
         }
 
-        if (!SELinux.restorecon(file)) {
-            throw new IOException("Failed to restorecon session dir");
+        if (!SELinux.restorecon(stageDir)) {
+            throw new IOException("Failed to restorecon session dir: " + stageDir);
         }
-
-        return file;
     }
 
-    private String prepareExternalStageCid(int sessionId, long sizeBytes) throws IOException {
-        if (sizeBytes <= 0) {
-            throw new IOException("Session must provide valid size for ASEC");
-        }
+    private String buildExternalStageCid(int sessionId) {
+        return "smdl" + sessionId + ".tmp";
+    }
 
-        final String cid = "smdl" + sessionId + ".tmp";
-        if (PackageHelper.createSdDir(sizeBytes, cid, PackageManagerService.getEncryptKey(),
+    static void prepareExternalStageCid(String stageCid, long sizeBytes) throws IOException {
+        if (PackageHelper.createSdDir(sizeBytes, stageCid, PackageManagerService.getEncryptKey(),
                 Process.SYSTEM_UID, true) == null) {
-            throw new IOException("Failed to create ASEC");
+            throw new IOException("Failed to create session cid: " + stageCid);
         }
-
-        return cid;
     }
 
     @Override
@@ -897,10 +840,9 @@
     private static class Callbacks extends Handler {
         private static final int MSG_SESSION_CREATED = 1;
         private static final int MSG_SESSION_BADGING_CHANGED = 2;
-        private static final int MSG_SESSION_OPENED = 3;
+        private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
         private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
-        private static final int MSG_SESSION_CLOSED = 5;
-        private static final int MSG_SESSION_FINISHED = 6;
+        private static final int MSG_SESSION_FINISHED = 5;
 
         private final RemoteCallbackList<IPackageInstallerCallback>
                 mCallbacks = new RemoteCallbackList<>();
@@ -945,15 +887,12 @@
                 case MSG_SESSION_BADGING_CHANGED:
                     callback.onSessionBadgingChanged(sessionId);
                     break;
-                case MSG_SESSION_OPENED:
-                    callback.onSessionOpened(sessionId);
+                case MSG_SESSION_ACTIVE_CHANGED:
+                    callback.onSessionActiveChanged(sessionId, (boolean) msg.obj);
                     break;
                 case MSG_SESSION_PROGRESS_CHANGED:
                     callback.onSessionProgressChanged(sessionId, (float) msg.obj);
                     break;
-                case MSG_SESSION_CLOSED:
-                    callback.onSessionClosed(sessionId);
-                    break;
                 case MSG_SESSION_FINISHED:
                     callback.onSessionFinished(sessionId, (boolean) msg.obj);
                     break;
@@ -968,18 +907,14 @@
             obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, userId).sendToTarget();
         }
 
-        private void notifySessionOpened(int sessionId, int userId) {
-            obtainMessage(MSG_SESSION_OPENED, sessionId, userId).sendToTarget();
+        private void notifySessionActiveChanged(int sessionId, int userId, boolean active) {
+            obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, userId, active).sendToTarget();
         }
 
         private void notifySessionProgressChanged(int sessionId, int userId, float progress) {
             obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, userId, progress).sendToTarget();
         }
 
-        private void notifySessionClosed(int sessionId, int userId) {
-            obtainMessage(MSG_SESSION_CLOSED, sessionId, userId).sendToTarget();
-        }
-
         public void notifySessionFinished(int sessionId, int userId, boolean success) {
             obtainMessage(MSG_SESSION_FINISHED, sessionId, userId, success).sendToTarget();
         }
@@ -1022,18 +957,14 @@
             writeSessionsAsync();
         }
 
-        public void onSessionOpened(PackageInstallerSession session) {
-            mCallbacks.notifySessionOpened(session.sessionId, session.userId);
+        public void onSessionActiveChanged(PackageInstallerSession session, boolean active) {
+            mCallbacks.notifySessionActiveChanged(session.sessionId, session.userId, active);
         }
 
         public void onSessionProgressChanged(PackageInstallerSession session, float progress) {
             mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress);
         }
 
-        public void onSessionClosed(PackageInstallerSession session) {
-            mCallbacks.notifySessionClosed(session.sessionId, session.userId);
-        }
-
         public void onSessionFinished(PackageInstallerSession session, boolean success) {
             mCallbacks.notifySessionFinished(session.sessionId, session.userId, success);
             synchronized (mSessions) {
@@ -1043,6 +974,12 @@
             writeSessionsAsync();
         }
 
+        public void onSessionPrepared(PackageInstallerSession session) {
+            // We prepared the destination to write into; we want to persist
+            // this, but it's not critical enough to block for.
+            writeSessionsAsync();
+        }
+
         public void onSessionSealed(PackageInstallerSession session) {
             // It's very important that we block until we've recorded the
             // session as being sealed, since we never want to allow mutation
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 85ff54e..adca46a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -17,15 +17,15 @@
 package com.android.server.pm;
 
 import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
-import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
 import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
-import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDONLY;
 import static android.system.OsConstants.O_WRONLY;
+import static com.android.server.pm.PackageInstallerService.prepareExternalStageCid;
+import static com.android.server.pm.PackageInstallerService.prepareInternalStageDir;
 
 import android.content.Context;
 import android.content.Intent;
@@ -88,8 +88,6 @@
     // TODO: enforce INSTALL_ALLOW_TEST
     // TODO: enforce INSTALL_ALLOW_DOWNGRADE
 
-    // TODO: treat INHERIT_EXISTING as installExistingPackage()
-
     private final PackageInstallerService.InternalCallback mCallback;
     private final Context mContext;
     private final PackageManagerService mPm;
@@ -108,18 +106,23 @@
     /** Note that UID is not persisted; it's always derived at runtime. */
     final int installerUid;
 
-    private final AtomicInteger mOpenCount = new AtomicInteger();
+    private final AtomicInteger mActiveCount = new AtomicInteger();
 
     private final Object mLock = new Object();
 
     @GuardedBy("mLock")
     private float mClientProgress = 0;
     @GuardedBy("mLock")
+    private float mInternalProgress = 0;
+
+    @GuardedBy("mLock")
     private float mProgress = 0;
     @GuardedBy("mLock")
     private float mReportedProgress = -1;
 
     @GuardedBy("mLock")
+    private boolean mPrepared = false;
+    @GuardedBy("mLock")
     private boolean mSealed = false;
     @GuardedBy("mLock")
     private boolean mPermissionsAccepted = false;
@@ -184,7 +187,7 @@
     public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
             Context context, PackageManagerService pm, Looper looper, int sessionId, int userId,
             String installerPackageName, SessionParams params, long createdMillis,
-            File stageDir, String stageCid, boolean sealed) {
+            File stageDir, String stageCid, boolean prepared, boolean sealed) {
         mCallback = callback;
         mContext = context;
         mPm = pm;
@@ -203,6 +206,7 @@
                     "Exactly one of stageDir or stageCid stage must be set");
         }
 
+        mPrepared = prepared;
         mSealed = sealed;
 
         // Always derived at runtime
@@ -214,8 +218,6 @@
         } else {
             mPermissionsAccepted = false;
         }
-
-        computeProgressLocked();
     }
 
     public SessionInfo generateInfo() {
@@ -227,7 +229,7 @@
                     mResolvedBaseFile.getAbsolutePath() : null;
             info.progress = mProgress;
             info.sealed = mSealed;
-            info.open = mOpenCount.get() > 0;
+            info.active = mActiveCount.get() > 0;
 
             info.mode = params.mode;
             info.sizeBytes = params.sizeBytes;
@@ -238,14 +240,23 @@
         return info;
     }
 
+    public boolean isPrepared() {
+        synchronized (mLock) {
+            return mPrepared;
+        }
+    }
+
     public boolean isSealed() {
         synchronized (mLock) {
             return mSealed;
         }
     }
 
-    private void assertNotSealed(String cookie) {
+    private void assertPreparedAndNotSealed(String cookie) {
         synchronized (mLock) {
+            if (!mPrepared) {
+                throw new IllegalStateException(cookie + " before prepared");
+            }
             if (mSealed) {
                 throw new SecurityException(cookie + " not allowed after commit");
             }
@@ -278,30 +289,26 @@
     @Override
     public void setClientProgress(float progress) {
         synchronized (mLock) {
+            // Always publish first staging movement
+            final boolean forcePublish = (mClientProgress == 0);
             mClientProgress = progress;
-            computeProgressLocked();
+            computeProgressLocked(forcePublish);
         }
-        maybePublishProgress();
     }
 
     @Override
     public void addClientProgress(float progress) {
         synchronized (mLock) {
-            mClientProgress += progress;
-            computeProgressLocked();
-        }
-        maybePublishProgress();
-    }
-
-    private void computeProgressLocked() {
-        if (mProgress <= 0.8f) {
-            mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f);
+            setClientProgress(mClientProgress + progress);
         }
     }
 
-    private void maybePublishProgress() {
+    private void computeProgressLocked(boolean forcePublish) {
+        mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f)
+                + MathUtils.constrain(mInternalProgress * 0.2f, 0f, 0.2f);
+
         // Only publish when meaningful change
-        if (Math.abs(mProgress - mReportedProgress) > 0.01) {
+        if (forcePublish || Math.abs(mProgress - mReportedProgress) >= 0.01) {
             mReportedProgress = mProgress;
             mCallback.onSessionProgressChanged(this, mProgress);
         }
@@ -309,7 +316,7 @@
 
     @Override
     public String[] getNames() {
-        assertNotSealed("getNames");
+        assertPreparedAndNotSealed("getNames");
         try {
             return resolveStageDir().list();
         } catch (IOException e) {
@@ -333,7 +340,7 @@
         // will block any attempted install transitions.
         final FileBridge bridge;
         synchronized (mLock) {
-            assertNotSealed("openWrite");
+            assertPreparedAndNotSealed("openWrite");
 
             bridge = new FileBridge();
             mBridges.add(bridge);
@@ -387,7 +394,7 @@
     }
 
     private ParcelFileDescriptor openReadInternal(String name) throws IOException {
-        assertNotSealed("openRead");
+        assertPreparedAndNotSealed("openRead");
 
         try {
             if (!FileUtils.isValidExtFilename(name)) {
@@ -407,6 +414,30 @@
     public void commit(IntentSender statusReceiver) {
         Preconditions.checkNotNull(statusReceiver);
 
+        synchronized (mLock) {
+            if (!mSealed) {
+                // Verify that all writers are hands-off
+                for (FileBridge bridge : mBridges) {
+                    if (!bridge.isClosed()) {
+                        throw new SecurityException("Files still open");
+                    }
+                }
+
+                // Persist the fact that we've sealed ourselves to prevent
+                // mutations of any hard links we create.
+                mSealed = true;
+                mCallback.onSessionSealed(this);
+            }
+        }
+
+        // Client staging is fully done at this point
+        mClientProgress = 1f;
+        computeProgressLocked(true);
+
+        // This ongoing commit should keep session active, even though client
+        // will probably close their end.
+        mActiveCount.incrementAndGet();
+
         final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
                 statusReceiver, sessionId);
         mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
@@ -414,22 +445,10 @@
 
     private void commitLocked() throws PackageManagerException {
         if (mDestroyed) {
-            throw new PackageManagerException(INSTALL_FAILED_ALREADY_EXISTS, "Invalid session");
+            throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
         }
-
-        // Verify that all writers are hands-off
         if (!mSealed) {
-            for (FileBridge bridge : mBridges) {
-                if (!bridge.isClosed()) {
-                    throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
-                            "Files still open");
-                }
-            }
-            mSealed = true;
-
-            // Persist the fact that we've sealed ourselves to prevent mutations
-            // of any hard links we create below.
-            mCallback.onSessionSealed(this);
+            throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
         }
 
         try {
@@ -458,6 +477,10 @@
                 mRemoteObserver.onUserActionRequired(intent);
             } catch (RemoteException ignored) {
             }
+
+            // Commit was keeping session marked as active until now; release
+            // that extra refcount so session appears idle.
+            close();
             return;
         }
 
@@ -487,8 +510,8 @@
         }
 
         // TODO: surface more granular state from dexopt
-        mProgress = 0.9f;
-        maybePublishProgress();
+        mInternalProgress = 0.5f;
+        computeProgressLocked(true);
 
         // Unpack native libraries
         extractNativeLibraries(mResolvedStageDir, params.abiOverride);
@@ -831,16 +854,36 @@
         }
     }
 
-    public void open() {
-        if (mOpenCount.getAndIncrement() == 0) {
-            mCallback.onSessionOpened(this);
+    public void open() throws IOException {
+        if (mActiveCount.getAndIncrement() == 0) {
+            mCallback.onSessionActiveChanged(this, true);
+        }
+
+        synchronized (mLock) {
+            if (!mPrepared) {
+                if (stageDir != null) {
+                    prepareInternalStageDir(stageDir);
+                } else if (stageCid != null) {
+                    prepareExternalStageCid(stageCid, params.sizeBytes);
+
+                    // TODO: deliver more granular progress for ASEC allocation
+                    mInternalProgress = 0.25f;
+                    computeProgressLocked(true);
+                } else {
+                    throw new IllegalArgumentException(
+                            "Exactly one of stageDir or stageCid stage must be set");
+                }
+
+                mPrepared = true;
+                mCallback.onSessionPrepared(this);
+            }
         }
     }
 
     @Override
     public void close() {
-        if (mOpenCount.decrementAndGet() == 0) {
-            mCallback.onSessionClosed(this);
+        if (mActiveCount.decrementAndGet() == 0) {
+            mCallback.onSessionActiveChanged(this, false);
         }
     }
 
@@ -869,6 +912,11 @@
         synchronized (mLock) {
             mSealed = true;
             mDestroyed = true;
+
+            // Force shut down all bridges
+            for (FileBridge bridge : mBridges) {
+                bridge.forceClose();
+            }
         }
         if (stageDir != null) {
             FileUtils.deleteContents(stageDir);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d2a627e..7b4270b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3783,21 +3783,25 @@
         } else {
             pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
         }
-        if ((flags&PackageManager.GET_PERMISSIONS) == 0) {
-            if (numMatch == permissions.length) {
-                pi.requestedPermissions = permissions;
-            } else {
-                pi.requestedPermissions = new String[numMatch];
-                numMatch = 0;
-                for (int i=0; i<permissions.length; i++) {
-                    if (tmp[i]) {
-                        pi.requestedPermissions[numMatch] = permissions[i];
-                        numMatch++;
+        // The above might return null in cases of uninstalled apps or install-state
+        // skew across users/profiles.
+        if (pi != null) {
+            if ((flags&PackageManager.GET_PERMISSIONS) == 0) {
+                if (numMatch == permissions.length) {
+                    pi.requestedPermissions = permissions;
+                } else {
+                    pi.requestedPermissions = new String[numMatch];
+                    numMatch = 0;
+                    for (int i=0; i<permissions.length; i++) {
+                        if (tmp[i]) {
+                            pi.requestedPermissions[numMatch] = permissions[i];
+                            numMatch++;
+                        }
                     }
                 }
             }
+            list.add(pi);
         }
-        list.add(pi);
     }
 
     @Override
@@ -10260,7 +10264,7 @@
                             || !bp.packageSetting.keySetData.isUsingUpgradeKeySets()
                             || ((PackageSetting) bp.packageSetting).sharedUser != null) {
                         sigsOk = compareSignatures(bp.packageSetting.signatures.mSignatures,
-                                pkg.mSignatures) != PackageManager.SIGNATURE_MATCH;
+                                pkg.mSignatures) == PackageManager.SIGNATURE_MATCH;
                     } else {
                         sigsOk = checkUpgradeKeySetLP((PackageSetting) bp.packageSetting, pkg);
                     }
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 3eb2d5f..802df95 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -85,6 +85,7 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.JournaledFile;
+import com.android.internal.R;
 
 public class WallpaperManagerService extends IWallpaperManager.Stub {
     static final String TAG = "WallpaperManagerService";
@@ -99,12 +100,6 @@
     static final long MIN_WALLPAPER_CRASH_TIME = 10000;
     static final String WALLPAPER = "wallpaper";
     static final String WALLPAPER_INFO = "wallpaper_info.xml";
-    /**
-     * Name of the component used to display bitmap wallpapers from either the gallery or
-     * built-in wallpapers.
-     */
-    static final ComponentName IMAGE_WALLPAPER = new ComponentName("com.android.systemui",
-            "com.android.systemui.ImageWallpaper");
 
     /**
      * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
@@ -146,7 +141,7 @@
                         if (event == CLOSE_WRITE) {
                             mWallpaper.imageWallpaperPending = false;
                         }
-                        bindWallpaperComponentLocked(IMAGE_WALLPAPER, true,
+                        bindWallpaperComponentLocked(mImageWallpaper, true,
                                 false, mWallpaper, null);
                         saveSettingsLocked(mWallpaper);
                     }
@@ -161,6 +156,12 @@
     final MyPackageMonitor mMonitor;
     WallpaperData mLastWallpaper;
 
+    /**
+     * Name of the component used to display bitmap wallpapers from either the gallery or
+     * built-in wallpapers.
+     */
+    final ComponentName mImageWallpaper;
+
     SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
 
     int mCurrentUserId;
@@ -447,6 +448,8 @@
     public WallpaperManagerService(Context context) {
         if (DEBUG) Slog.v(TAG, "WallpaperService startup");
         mContext = context;
+        mImageWallpaper = ComponentName.unflattenFromString(
+                context.getResources().getString(R.string.image_wallpaper_component));
         mIWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
         mIPackageManager = AppGlobals.getPackageManager();
@@ -599,33 +602,35 @@
             f.delete();
         }
         final long ident = Binder.clearCallingIdentity();
-        RuntimeException e = null;
         try {
-            wallpaper.imageWallpaperPending = false;
-            if (userId != mCurrentUserId) return;
-            if (bindWallpaperComponentLocked(defaultFailed
-                    ? IMAGE_WALLPAPER
-                    : null, true, false, wallpaper, reply)) {
-                return;
+            RuntimeException e = null;
+            try {
+                wallpaper.imageWallpaperPending = false;
+                if (userId != mCurrentUserId) return;
+                if (bindWallpaperComponentLocked(defaultFailed
+                        ? mImageWallpaper
+                                : null, true, false, wallpaper, reply)) {
+                    return;
+                }
+            } catch (IllegalArgumentException e1) {
+                e = e1;
             }
-        } catch (IllegalArgumentException e1) {
-            e = e1;
+
+            // This can happen if the default wallpaper component doesn't
+            // exist.  This should be a system configuration problem, but
+            // let's not let it crash the system and just live with no
+            // wallpaper.
+            Slog.e(TAG, "Default wallpaper component not found!", e);
+            clearWallpaperComponentLocked(wallpaper);
+            if (reply != null) {
+                try {
+                    reply.sendResult(null);
+                } catch (RemoteException e1) {
+                }
+            }
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
-        
-        // This can happen if the default wallpaper component doesn't
-        // exist.  This should be a system configuration problem, but
-        // let's not let it crash the system and just live with no
-        // wallpaper.
-        Slog.e(TAG, "Default wallpaper component not found!", e);
-        clearWallpaperComponentLocked(wallpaper);
-        if (reply != null) {
-            try {
-                reply.sendResult(null);
-            } catch (RemoteException e1) {
-            }
-        }
     }
 
     public boolean hasNamedWallpaper(String name) {
@@ -848,7 +853,7 @@
                 componentName = WallpaperManager.getDefaultWallpaperComponent(mContext);
                 if (componentName == null) {
                     // Fall back to static image wallpaper
-                    componentName = IMAGE_WALLPAPER;
+                    componentName = mImageWallpaper;
                     //clearWallpaperComponentLocked();
                     //return;
                     if (DEBUG) Slog.v(TAG, "Using image wallpaper");
@@ -876,7 +881,7 @@
             WallpaperInfo wi = null;
             
             Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
-            if (componentName != null && !componentName.equals(IMAGE_WALLPAPER)) {
+            if (componentName != null && !componentName.equals(mImageWallpaper)) {
                 // Make sure the selected service is actually a wallpaper service.
                 List<ResolveInfo> ris =
                         mIPackageManager.queryIntentServices(intent,
@@ -1052,7 +1057,7 @@
             out.attribute(null, "height", Integer.toString(wallpaper.height));
             out.attribute(null, "name", wallpaper.name);
             if (wallpaper.wallpaperComponent != null
-                    && !wallpaper.wallpaperComponent.equals(IMAGE_WALLPAPER)) {
+                    && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
                 out.attribute(null, "component",
                         wallpaper.wallpaperComponent.flattenToShortString());
             }
@@ -1124,7 +1129,7 @@
                         if (wallpaper.nextWallpaperComponent == null
                                 || "android".equals(wallpaper.nextWallpaperComponent
                                         .getPackageName())) {
-                            wallpaper.nextWallpaperComponent = IMAGE_WALLPAPER;
+                            wallpaper.nextWallpaperComponent = mImageWallpaper;
                         }
                           
                         if (DEBUG) {
@@ -1196,7 +1201,7 @@
             loadSettingsLocked(0);
             wallpaper = mWallpaperMap.get(0);
             if (wallpaper.nextWallpaperComponent != null
-                    && !wallpaper.nextWallpaperComponent.equals(IMAGE_WALLPAPER)) {
+                    && !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) {
                 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
                         wallpaper, null)) {
                     // No such live wallpaper or other failure; fall back to the default
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index aabb8f7..bfc7659 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -569,9 +569,9 @@
             int appWidth, int appHeight, int orientation, int transit, Rect containingFrame,
             Rect contentInsets, boolean isFullScreen) {
         Animation a;
-        final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
+        final int thumbWidthI = mNextAppTransitionStartWidth;
         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
-        final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
+        final int thumbHeightI = mNextAppTransitionStartHeight;
         final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
 
         // Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions
@@ -993,7 +993,7 @@
     }
 
     void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY,
-            IRemoteCallback startedCallback, boolean scaleUp) {
+            int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp) {
         if (isTransitionSet()) {
             mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
                     : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
@@ -1002,6 +1002,8 @@
             mNextAppTransitionScaleUp = scaleUp;
             mNextAppTransitionStartX = startX;
             mNextAppTransitionStartY = startY;
+            mNextAppTransitionStartWidth = targetWidth;
+            mNextAppTransitionStartHeight = targetHeight;
             postAnimationCallback();
             mNextAppTransitionCallback = startedCallback;
         } else {
@@ -1138,6 +1140,10 @@
                         pw.print(mNextAppTransitionStartX);
                         pw.print(" mNextAppTransitionStartY=");
                         pw.println(mNextAppTransitionStartY);
+                        pw.print(" mNextAppTransitionStartWidth=");
+                        pw.print(mNextAppTransitionStartWidth);
+                        pw.print(" mNextAppTransitionStartHeight=");
+                        pw.println(mNextAppTransitionStartHeight);
                 pw.print("  mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp);
                 break;
         }
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index d0f00d4..46aefb6 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -365,12 +365,13 @@
         return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
     }
 
-    /* Provides an opportunity for the window manager policy to intercept early
-     * motion event processing when the screen is off since these events are normally
+    /* Provides an opportunity for the window manager policy to intercept early motion event
+     * processing when the device is in a non-interactive state since these events are normally
      * dropped. */
     @Override
-    public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
-        return mService.mPolicy.interceptWakeMotionBeforeQueueing(whenNanos, policyFlags);
+    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
+        return mService.mPolicy.interceptMotionBeforeQueueingNonInteractive(
+                whenNanos, policyFlags);
     }
 
     /* Provides an opportunity for the window manager policy to process a key before
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a1afe29..55c6d81 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4031,10 +4031,11 @@
 
     @Override
     public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
-            int startY, IRemoteCallback startedCallback, boolean scaleUp) {
+            int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
+            boolean scaleUp) {
         synchronized(mWindowMap) {
             mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX,
-                    startY, startedCallback, scaleUp);
+                    startY, targetWidth, targetHeight, startedCallback, scaleUp);
         }
     }
 
@@ -4303,20 +4304,28 @@
     }
 
     public void setAppFullscreen(IBinder token, boolean toOpaque) {
-        AppWindowToken atoken = findAppWindowToken(token);
-        if (atoken != null) {
-            atoken.appFullscreen = toOpaque;
-            setWindowOpaque(token, toOpaque);
-            requestTraversal();
+        synchronized (mWindowMap) {
+            AppWindowToken atoken = findAppWindowToken(token);
+            if (atoken != null) {
+                atoken.appFullscreen = toOpaque;
+                setWindowOpaqueLocked(token, toOpaque);
+                requestTraversalLocked();
+            }
         }
     }
 
     public void setWindowOpaque(IBinder token, boolean isOpaque) {
+        synchronized (mWindowMap) {
+            setWindowOpaqueLocked(token, isOpaque);
+        }
+    }
+
+    public void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
         AppWindowToken wtoken = findAppWindowToken(token);
         if (wtoken != null) {
             WindowState win = wtoken.findMainWindow();
             if (win != null) {
-                win.mWinAnimator.setOpaque(isOpaque);
+                win.mWinAnimator.setOpaqueLocked(isOpaque);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 3d4be12..a871522 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1556,11 +1556,11 @@
         }
     }
 
-    void setOpaque(boolean isOpaque) {
+    void setOpaqueLocked(boolean isOpaque) {
         if (mSurfaceControl == null) {
             return;
         }
-        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaque");
+        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaqueLocked");
         SurfaceControl.openTransaction();
         try {
             if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "isOpaque=" + isOpaque,
@@ -1568,7 +1568,7 @@
             mSurfaceControl.setOpaque(isOpaque);
         } finally {
             SurfaceControl.closeTransaction();
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaque");
+            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaqueLocked");
         }
     }
 
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 8ed74be..cddca92 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -71,7 +71,7 @@
     jmethodID notifyANR;
     jmethodID filterInputEvent;
     jmethodID interceptKeyBeforeQueueing;
-    jmethodID interceptWakeMotionBeforeQueueing;
+    jmethodID interceptMotionBeforeQueueingNonInteractive;
     jmethodID interceptKeyBeforeDispatching;
     jmethodID dispatchUnhandledKey;
     jmethodID checkInjectEventsPermission;
@@ -854,7 +854,9 @@
 
         handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
     } else {
-        policyFlags |= POLICY_FLAG_PASS_TO_USER;
+        if (mInteractive) {
+            policyFlags |= POLICY_FLAG_PASS_TO_USER;
+        }
     }
 }
 
@@ -870,20 +872,22 @@
     if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {
         if (policyFlags & POLICY_FLAG_INTERACTIVE) {
             policyFlags |= POLICY_FLAG_PASS_TO_USER;
-        } else if (policyFlags & POLICY_FLAG_WAKE) {
+        } else {
             JNIEnv* env = jniEnv();
             jint wmActions = env->CallIntMethod(mServiceObj,
-                        gServiceClassInfo.interceptWakeMotionBeforeQueueing,
+                        gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive,
                         when, policyFlags);
             if (checkAndClearExceptionFromCallback(env,
-                    "interceptWakeMotionBeforeQueueing")) {
+                    "interceptMotionBeforeQueueingNonInteractive")) {
                 wmActions = 0;
             }
 
             handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
         }
     } else {
-        policyFlags |= POLICY_FLAG_PASS_TO_USER;
+        if (mInteractive) {
+            policyFlags |= POLICY_FLAG_PASS_TO_USER;
+        }
     }
 }
 
@@ -1441,8 +1445,8 @@
     GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
             "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I");
 
-    GET_METHOD_ID(gServiceClassInfo.interceptWakeMotionBeforeQueueing, clazz,
-            "interceptWakeMotionBeforeQueueing", "(JI)I");
+    GET_METHOD_ID(gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive, clazz,
+            "interceptMotionBeforeQueueingNonInteractive", "(JI)I");
 
     GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
             "interceptKeyBeforeDispatching",
diff --git a/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java b/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
index fb29b6a..218f899 100644
--- a/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
+++ b/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
@@ -139,7 +139,7 @@
         }
 
         @Override
-        public Intent getLocalApprovalIntent() throws RemoteException {
+        public Intent createLocalApprovalIntent() throws RemoteException {
             if (DEBUG) {
                 Log.i(LOG_TAG, "requestPermission");
             }
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 6c80a65..5f639ab 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -23,13 +23,11 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
-import java.util.ArrayList;
-
 class IntervalStats {
     public long beginTime;
     public long endTime;
     public long lastTimeSaved;
-    public final ArrayMap<String, UsageStats> stats = new ArrayMap<>();
+    public final ArrayMap<String, UsageStats> packageStats = new ArrayMap<>();
     public final ArrayMap<Configuration, ConfigurationStats> configurations = new ArrayMap<>();
     public Configuration activeConfiguration;
     public TimeSparseArray<UsageEvents.Event> events;
@@ -44,13 +42,13 @@
      * Gets the UsageStats object for the given package, or creates one and adds it internally.
      */
     UsageStats getOrCreateUsageStats(String packageName) {
-        UsageStats usageStats = stats.get(packageName);
+        UsageStats usageStats = packageStats.get(packageName);
         if (usageStats == null) {
             usageStats = new UsageStats();
             usageStats.mPackageName = getCachedStringRef(packageName);
             usageStats.mBeginTimeStamp = beginTime;
             usageStats.mEndTimeStamp = endTime;
-            stats.put(usageStats.mPackageName, usageStats);
+            packageStats.put(usageStats.mPackageName, usageStats);
         }
         return usageStats;
     }
diff --git a/services/usage/java/com/android/server/usage/UnixCalendar.java b/services/usage/java/com/android/server/usage/UnixCalendar.java
new file mode 100644
index 0000000..ce06a91
--- /dev/null
+++ b/services/usage/java/com/android/server/usage/UnixCalendar.java
@@ -0,0 +1,99 @@
+/**
+ * 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.server.usage;
+
+import android.app.usage.UsageStatsManager;
+
+/**
+ * A handy calendar object that knows nothing of Locale's or TimeZones. This simplifies
+ * interval book-keeping. It is *NOT* meant to be used as a user-facing calendar, as it has
+ * no concept of Locale or TimeZone.
+ */
+public class UnixCalendar {
+    private static final long DAY_IN_MILLIS = 24 * 60 * 60 * 1000;
+    private static final long WEEK_IN_MILLIS = 7 * DAY_IN_MILLIS;
+    private static final long MONTH_IN_MILLIS = 30 * DAY_IN_MILLIS;
+    private static final long YEAR_IN_MILLIS = 365 * DAY_IN_MILLIS;
+    private long mTime;
+
+    public UnixCalendar(long time) {
+        mTime = time;
+    }
+
+    public void truncateToDay() {
+        mTime -= mTime % DAY_IN_MILLIS;
+    }
+
+    public void truncateToWeek() {
+        mTime -= mTime % WEEK_IN_MILLIS;
+    }
+
+    public void truncateToMonth() {
+        mTime -= mTime % MONTH_IN_MILLIS;
+    }
+
+    public void truncateToYear() {
+        mTime -= mTime % YEAR_IN_MILLIS;
+    }
+
+    public void addDays(int val) {
+        mTime += val * DAY_IN_MILLIS;
+    }
+
+    public void addWeeks(int val) {
+        mTime += val * WEEK_IN_MILLIS;
+    }
+
+    public void addMonths(int val) {
+        mTime += val * MONTH_IN_MILLIS;
+    }
+
+    public void addYears(int val) {
+        mTime += val * YEAR_IN_MILLIS;
+    }
+
+    public void setTimeInMillis(long time) {
+        mTime = time;
+    }
+
+    public long getTimeInMillis() {
+        return mTime;
+    }
+
+    public static void truncateTo(UnixCalendar calendar, int intervalType) {
+        switch (intervalType) {
+            case UsageStatsManager.INTERVAL_YEARLY:
+                calendar.truncateToYear();
+                break;
+
+            case UsageStatsManager.INTERVAL_MONTHLY:
+                calendar.truncateToMonth();
+                break;
+
+            case UsageStatsManager.INTERVAL_WEEKLY:
+                calendar.truncateToWeek();
+                break;
+
+            case UsageStatsManager.INTERVAL_DAILY:
+                calendar.truncateToDay();
+                break;
+
+            default:
+                throw new UnsupportedOperationException("Can't truncate date to interval " +
+                        intervalType);
+        }
+    }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 37340a4..62a7ec0 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -21,24 +21,30 @@
 import android.util.AtomicFile;
 import android.util.Slog;
 
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
 import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
 import java.io.FilenameFilter;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Calendar;
 import java.util.List;
 
 /**
  * Provides an interface to query for UsageStat data from an XML database.
  */
 class UsageStatsDatabase {
+    private static final int CURRENT_VERSION = 2;
+
     private static final String TAG = "UsageStatsDatabase";
     private static final boolean DEBUG = UsageStatsService.DEBUG;
 
     private final Object mLock = new Object();
     private final File[] mIntervalDirs;
     private final TimeSparseArray<AtomicFile>[] mSortedStatFiles;
-    private final Calendar mCal;
+    private final UnixCalendar mCal;
+    private final File mVersionFile;
 
     public UsageStatsDatabase(File dir) {
         mIntervalDirs = new File[] {
@@ -47,8 +53,9 @@
                 new File(dir, "monthly"),
                 new File(dir, "yearly"),
         };
+        mVersionFile = new File(dir, "version");
         mSortedStatFiles = new TimeSparseArray[mIntervalDirs.length];
-        mCal = Calendar.getInstance();
+        mCal = new UnixCalendar(0);
     }
 
     /**
@@ -64,6 +71,8 @@
                 }
             }
 
+            checkVersionLocked();
+
             final FilenameFilter backupFileFilter = new FilenameFilter() {
                 @Override
                 public boolean accept(File dir, String name) {
@@ -81,7 +90,45 @@
                     }
 
                     for (File f : files) {
-                        mSortedStatFiles[i].put(Long.parseLong(f.getName()), new AtomicFile(f));
+                        final AtomicFile af = new AtomicFile(f);
+                        mSortedStatFiles[i].put(UsageStatsXml.parseBeginTime(af), af);
+                    }
+                }
+            }
+        }
+    }
+
+    private void checkVersionLocked() {
+        int version;
+        try (BufferedReader reader = new BufferedReader(new FileReader(mVersionFile))) {
+            version = Integer.parseInt(reader.readLine());
+        } catch (NumberFormatException | IOException e) {
+            version = 0;
+        }
+
+        if (version != CURRENT_VERSION) {
+            Slog.i(TAG, "Upgrading from version " + version + " to " + CURRENT_VERSION);
+            doUpgradeLocked(version);
+
+            try (BufferedWriter writer = new BufferedWriter(new FileWriter(mVersionFile))) {
+                writer.write(Integer.toString(CURRENT_VERSION));
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to write new version");
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    private void doUpgradeLocked(int thisVersion) {
+        if (thisVersion < 2) {
+            // Delete all files if we are version 0. This is a pre-release version,
+            // so this is fine.
+            Slog.i(TAG, "Deleting all usage stats files");
+            for (int i = 0; i < mIntervalDirs.length; i++) {
+                File[] files = mIntervalDirs[i].listFiles();
+                if (files != null) {
+                    for (File f : files) {
+                        f.delete();
                     }
                 }
             }
@@ -161,25 +208,48 @@
                 throw new IllegalArgumentException("Bad interval type " + intervalType);
             }
 
-            if (endTime < beginTime) {
+            final TimeSparseArray<AtomicFile> intervalStats = mSortedStatFiles[intervalType];
+
+            if (endTime <= beginTime) {
+                if (DEBUG) {
+                    Slog.d(TAG, "endTime(" + endTime + ") <= beginTime(" + beginTime + ")");
+                }
                 return null;
             }
 
-            final int startIndex = mSortedStatFiles[intervalType].closestIndexOnOrBefore(beginTime);
+            int startIndex = intervalStats.closestIndexOnOrBefore(beginTime);
             if (startIndex < 0) {
+                // All the stats available have timestamps after beginTime, which means they all
+                // match.
+                startIndex = 0;
+            }
+
+            int endIndex = intervalStats.closestIndexOnOrBefore(endTime);
+            if (endIndex < 0) {
+                // All the stats start after this range ends, so nothing matches.
+                if (DEBUG) {
+                    Slog.d(TAG, "No results for this range. All stats start after.");
+                }
                 return null;
             }
 
-            int endIndex = mSortedStatFiles[intervalType].closestIndexOnOrAfter(endTime);
-            if (endIndex < 0) {
-                endIndex = mSortedStatFiles[intervalType].size() - 1;
+            if (intervalStats.keyAt(endIndex) == endTime) {
+                // The endTime is exclusive, so if we matched exactly take the one before.
+                endIndex--;
+                if (endIndex < 0) {
+                    // All the stats start after this range ends, so nothing matches.
+                    if (DEBUG) {
+                        Slog.d(TAG, "No results for this range. All stats start after.");
+                    }
+                    return null;
+                }
             }
 
             try {
                 IntervalStats stats = new IntervalStats();
                 ArrayList<T> results = new ArrayList<>();
                 for (int i = startIndex; i <= endIndex; i++) {
-                    final AtomicFile f = mSortedStatFiles[intervalType].valueAt(i);
+                    final AtomicFile f = intervalStats.valueAt(i);
 
                     if (DEBUG) {
                         Slog.d(TAG, "Reading stat file " + f.getBaseFile().getAbsolutePath());
@@ -230,22 +300,22 @@
         synchronized (mLock) {
             long timeNow = System.currentTimeMillis();
             mCal.setTimeInMillis(timeNow);
-            mCal.add(Calendar.YEAR, -3);
+            mCal.addYears(-3);
             pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_YEARLY],
                     mCal.getTimeInMillis());
 
             mCal.setTimeInMillis(timeNow);
-            mCal.add(Calendar.MONTH, -6);
+            mCal.addMonths(-6);
             pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_MONTHLY],
                     mCal.getTimeInMillis());
 
             mCal.setTimeInMillis(timeNow);
-            mCal.add(Calendar.WEEK_OF_YEAR, -4);
+            mCal.addWeeks(-4);
             pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_WEEKLY],
                     mCal.getTimeInMillis());
 
             mCal.setTimeInMillis(timeNow);
-            mCal.add(Calendar.DAY_OF_YEAR, -7);
+            mCal.addDays(-7);
             pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_DAILY],
                     mCal.getTimeInMillis());
         }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index e77bf86..2dcdcc4 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -38,6 +38,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.ArraySet;
@@ -62,9 +63,7 @@
     static final boolean DEBUG = false;
     private static final long TEN_SECONDS = 10 * 1000;
     private static final long TWENTY_MINUTES = 20 * 60 * 1000;
-    private static final long TWO_MINUTES = 2 * 60 * 1000;
     private static final long FLUSH_INTERVAL = DEBUG ? TEN_SECONDS : TWENTY_MINUTES;
-    private static final long END_TIME_DELAY = DEBUG ? 0 : TWO_MINUTES;
 
     // Handler message types.
     static final int MSG_REPORT_EVENT = 0;
@@ -78,6 +77,8 @@
 
     private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
     private File mUsageStatsDir;
+    long mRealTimeSnapshot;
+    long mSystemTimeSnapshot;
 
     public UsageStatsService(Context context) {
         super(context);
@@ -104,6 +105,9 @@
             cleanUpRemovedUsersLocked();
         }
 
+        mRealTimeSnapshot = SystemClock.elapsedRealtime();
+        mSystemTimeSnapshot = System.currentTimeMillis();
+
         publishLocalService(UsageStatsManagerInternal.class, new LocalService());
         publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
     }
@@ -178,7 +182,7 @@
     }
 
     /**
-     * Called by the Bunder stub
+     * Called by the Binder stub
      */
     void shutdown() {
         synchronized (mLock) {
@@ -382,6 +386,14 @@
      */
     private class LocalService extends UsageStatsManagerInternal {
 
+        /**
+         * The system may have its time change, so at least make sure the events
+         * are monotonic in order.
+         */
+        private long computeMonotonicSystemTime(long realTime) {
+            return (realTime - mRealTimeSnapshot) + mSystemTimeSnapshot;
+        }
+
         @Override
         public void reportEvent(ComponentName component, int userId, int eventType) {
             if (component == null) {
@@ -392,7 +404,7 @@
             UsageEvents.Event event = new UsageEvents.Event();
             event.mPackage = component.getPackageName();
             event.mClass = component.getClassName();
-            event.mTimeStamp = System.currentTimeMillis();
+            event.mTimeStamp = computeMonotonicSystemTime(SystemClock.elapsedRealtime());
             event.mEventType = eventType;
             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
         }
@@ -406,7 +418,7 @@
 
             UsageEvents.Event event = new UsageEvents.Event();
             event.mPackage = "android";
-            event.mTimeStamp = System.currentTimeMillis();
+            event.mTimeStamp = computeMonotonicSystemTime(SystemClock.elapsedRealtime());
             event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE;
             event.mConfiguration = new Configuration(config);
             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
diff --git a/services/usage/java/com/android/server/usage/UsageStatsUtils.java b/services/usage/java/com/android/server/usage/UsageStatsUtils.java
deleted file mode 100644
index dd5f3b9..0000000
--- a/services/usage/java/com/android/server/usage/UsageStatsUtils.java
+++ /dev/null
@@ -1,63 +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.server.usage;
-
-import android.app.usage.UsageStatsManager;
-
-import java.util.Calendar;
-
-/**
- * A collection of utility methods used by the UsageStatsService and accompanying classes.
- */
-final class UsageStatsUtils {
-    private UsageStatsUtils() {}
-
-    /**
-     * Truncates the date to the given UsageStats bucket. For example, if the bucket is
-     * {@link UsageStatsManager#INTERVAL_YEARLY}, the date is truncated to the 1st day of the year,
-     * with the time set to 00:00:00.
-     *
-     * @param bucket The UsageStats bucket to truncate to.
-     * @param cal The date to truncate.
-     */
-    public static void truncateDateTo(int bucket, Calendar cal) {
-        cal.set(Calendar.HOUR_OF_DAY, 0);
-        cal.set(Calendar.MINUTE, 0);
-        cal.set(Calendar.SECOND, 0);
-        cal.set(Calendar.MILLISECOND, 0);
-
-        switch (bucket) {
-            case UsageStatsManager.INTERVAL_YEARLY:
-                cal.set(Calendar.DAY_OF_YEAR, 0);
-                break;
-
-            case UsageStatsManager.INTERVAL_MONTHLY:
-                cal.set(Calendar.DAY_OF_MONTH, 0);
-                break;
-
-            case UsageStatsManager.INTERVAL_WEEKLY:
-                cal.set(Calendar.DAY_OF_WEEK, 0);
-                break;
-
-            case UsageStatsManager.INTERVAL_DAILY:
-                break;
-
-            default:
-                throw new UnsupportedOperationException("Can't truncate date to bucket " + bucket);
-        }
-    }
-}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXml.java b/services/usage/java/com/android/server/usage/UsageStatsXml.java
index 48881d0..9ce6d63 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXml.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXml.java
@@ -37,10 +37,15 @@
     private static final String USAGESTATS_TAG = "usagestats";
     private static final String VERSION_ATTR = "version";
 
+    public static long parseBeginTime(AtomicFile file) {
+        return Long.parseLong(file.getBaseFile().getName());
+    }
+
     public static void read(AtomicFile file, IntervalStats statsOut) throws IOException {
         try {
             FileInputStream in = file.openRead();
             try {
+                statsOut.beginTime = parseBeginTime(file);
                 read(in, statsOut);
                 statsOut.lastTimeSaved = file.getLastModifiedTime();
             } finally {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index 6529950..ef95a7b 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -15,7 +15,6 @@
  */
 package com.android.server.usage;
 
-import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -26,44 +25,52 @@
 import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
-import android.content.ComponentName;
 import android.content.res.Configuration;
 
 import java.io.IOException;
 import java.net.ProtocolException;
-import java.util.Locale;
 
 /**
  * UsageStats reader/writer for version 1 of the XML format.
  */
 final class UsageStatsXmlV1 {
+    private static final String PACKAGES_TAG = "packages";
     private static final String PACKAGE_TAG = "package";
-    private static final String CONFIGURATION_TAG = "config";
-    private static final String EVENT_LOG_TAG = "event-log";
 
-    private static final String BEGIN_TIME_ATTR = "beginTime";
-    private static final String END_TIME_ATTR = "endTime";
-    private static final String NAME_ATTR = "name";
+    private static final String CONFIGURATIONS_TAG = "configurations";
+    private static final String CONFIG_TAG = "config";
+
+    private static final String EVENT_LOG_TAG = "event-log";
+    private static final String EVENT_TAG = "event";
+
+    // Attributes
     private static final String PACKAGE_ATTR = "package";
     private static final String CLASS_ATTR = "class";
-    private static final String TOTAL_TIME_ACTIVE_ATTR = "totalTimeActive";
-    private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
+    private static final String TOTAL_TIME_ACTIVE_ATTR = "timeActive";
     private static final String COUNT_ATTR = "count";
     private static final String ACTIVE_ATTR = "active";
     private static final String LAST_EVENT_ATTR = "lastEvent";
     private static final String TYPE_ATTR = "type";
+
+    // Time attributes stored as an offset of the beginTime.
+    private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
+    private static final String END_TIME_ATTR = "endTime";
     private static final String TIME_ATTR = "time";
 
     private static void loadUsageStats(XmlPullParser parser, IntervalStats statsOut)
             throws XmlPullParserException, IOException {
-        final String name = parser.getAttributeValue(null, NAME_ATTR);
-        if (name == null) {
-            throw new ProtocolException("no " + NAME_ATTR + " attribute present");
+        final String pkg = parser.getAttributeValue(null, PACKAGE_ATTR);
+        if (pkg == null) {
+            throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present");
         }
 
-        UsageStats stats = statsOut.getOrCreateUsageStats(name);
+        final UsageStats stats = statsOut.getOrCreateUsageStats(pkg);
+
+        // Apply the offset to the beginTime to find the absolute time.
+        stats.mLastTimeUsed = statsOut.beginTime + XmlUtils.readLongAttribute(
+                parser, LAST_TIME_ACTIVE_ATTR);
+
         stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
-        stats.mLastTimeUsed = XmlUtils.readLongAttribute(parser, LAST_TIME_ACTIVE_ATTR);
         stats.mLastEvent = XmlUtils.readIntAttribute(parser, LAST_EVENT_ATTR);
     }
 
@@ -72,8 +79,12 @@
         final Configuration config = new Configuration();
         Configuration.readXmlAttrs(parser, config);
 
-        ConfigurationStats configStats = statsOut.getOrCreateConfigurationStats(config);
-        configStats.mLastTimeActive = XmlUtils.readLongAttribute(parser, LAST_TIME_ACTIVE_ATTR);
+        final ConfigurationStats configStats = statsOut.getOrCreateConfigurationStats(config);
+
+        // Apply the offset to the beginTime to find the absolute time.
+        configStats.mLastTimeActive = statsOut.beginTime + XmlUtils.readLongAttribute(
+                parser, LAST_TIME_ACTIVE_ATTR);
+
         configStats.mTotalTimeActive = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
         configStats.mActivationCount = XmlUtils.readIntAttribute(parser, COUNT_ATTR);
         if (XmlUtils.readBooleanAttribute(parser, ACTIVE_ATTR)) {
@@ -83,30 +94,19 @@
 
     private static void loadEvent(XmlPullParser parser, IntervalStats statsOut)
             throws XmlPullParserException, IOException {
-        String packageName = XmlUtils.readStringAttribute(parser, PACKAGE_ATTR);
-        String className;
+        final String packageName = XmlUtils.readStringAttribute(parser, PACKAGE_ATTR);
         if (packageName == null) {
-            // Try getting the component name if it exists.
-            final String componentName = XmlUtils.readStringAttribute(parser, NAME_ATTR);
-            if (componentName == null) {
-                throw new ProtocolException("no " + NAME_ATTR + " or " + PACKAGE_ATTR +
-                        " attribute present");
-            }
-            ComponentName component = ComponentName.unflattenFromString(componentName);
-            if (component == null) {
-                throw new ProtocolException("ComponentName " + componentName + " is invalid");
-            }
-
-            packageName = component.getPackageName();
-            className = component.getClassName();
-        } else {
-            className = XmlUtils.readStringAttribute(parser, CLASS_ATTR);
+            throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present");
         }
 
-        UsageEvents.Event event = statsOut.buildEvent(packageName, className);
-        event.mEventType = XmlUtils.readIntAttribute(parser, TYPE_ATTR);
-        event.mTimeStamp = XmlUtils.readLongAttribute(parser, TIME_ATTR);
+        final String className = XmlUtils.readStringAttribute(parser, CLASS_ATTR);
 
+        final UsageEvents.Event event = statsOut.buildEvent(packageName, className);
+
+        // Apply the offset to the beginTime to find the absolute time of this event.
+        event.mTimeStamp = statsOut.beginTime + XmlUtils.readLongAttribute(parser, TIME_ATTR);
+
+        event.mEventType = XmlUtils.readIntAttribute(parser, TYPE_ATTR);
         if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE) {
             event.mConfiguration = new Configuration();
             Configuration.readXmlAttrs(parser, event.mConfiguration);
@@ -118,48 +118,60 @@
         statsOut.events.put(event.mTimeStamp, event);
     }
 
-    private static void writeUsageStats(XmlSerializer xml, final UsageStats stats)
-            throws IOException {
+    private static void writeUsageStats(XmlSerializer xml, final IntervalStats stats,
+            final UsageStats usageStats) throws IOException {
         xml.startTag(null, PACKAGE_TAG);
-        XmlUtils.writeStringAttribute(xml, NAME_ATTR, stats.mPackageName);
-        XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, stats.mTotalTimeInForeground);
-        XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR, stats.mLastTimeUsed);
-        XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, stats.mLastEvent);
+
+        // Write the time offset.
+        XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR,
+                usageStats.mLastTimeUsed - stats.beginTime);
+
+        XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, usageStats.mPackageName);
+        XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, usageStats.mTotalTimeInForeground);
+        XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, usageStats.mLastEvent);
+
         xml.endTag(null, PACKAGE_TAG);
     }
 
-    private static void writeConfigStats(XmlSerializer xml, final ConfigurationStats stats,
-            boolean isActive) throws IOException {
-        xml.startTag(null, CONFIGURATION_TAG);
-        XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR, stats.mLastTimeActive);
-        XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, stats.mTotalTimeActive);
-        XmlUtils.writeIntAttribute(xml, COUNT_ATTR, stats.mActivationCount);
+    private static void writeConfigStats(XmlSerializer xml, final IntervalStats stats,
+            final ConfigurationStats configStats, boolean isActive) throws IOException {
+        xml.startTag(null, CONFIG_TAG);
+
+        // Write the time offset.
+        XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR,
+                configStats.mLastTimeActive - stats.beginTime);
+
+        XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, configStats.mTotalTimeActive);
+        XmlUtils.writeIntAttribute(xml, COUNT_ATTR, configStats.mActivationCount);
         if (isActive) {
             XmlUtils.writeBooleanAttribute(xml, ACTIVE_ATTR, true);
         }
 
         // Now write the attributes representing the configuration object.
-        Configuration.writeXmlAttrs(xml, stats.mConfiguration);
+        Configuration.writeXmlAttrs(xml, configStats.mConfiguration);
 
-        xml.endTag(null, CONFIGURATION_TAG);
+        xml.endTag(null, CONFIG_TAG);
     }
 
-    private static void writeEvent(XmlSerializer xml, final UsageEvents.Event event)
-            throws IOException {
-        xml.startTag(null, EVENT_LOG_TAG);
+    private static void writeEvent(XmlSerializer xml, final IntervalStats stats,
+            final UsageEvents.Event event) throws IOException {
+        xml.startTag(null, EVENT_TAG);
+
+        // Store the time offset.
+        XmlUtils.writeLongAttribute(xml, TIME_ATTR, event.mTimeStamp - stats.beginTime);
+
         XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, event.mPackage);
         if (event.mClass != null) {
             XmlUtils.writeStringAttribute(xml, CLASS_ATTR, event.mClass);
         }
         XmlUtils.writeIntAttribute(xml, TYPE_ATTR, event.mEventType);
-        XmlUtils.writeLongAttribute(xml, TIME_ATTR, event.mTimeStamp);
 
         if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE
                 && event.mConfiguration != null) {
             Configuration.writeXmlAttrs(xml, event.mConfiguration);
         }
 
-        xml.endTag(null, EVENT_LOG_TAG);
+        xml.endTag(null, EVENT_TAG);
     }
 
     /**
@@ -171,7 +183,7 @@
      */
     public static void read(XmlPullParser parser, IntervalStats statsOut)
             throws XmlPullParserException, IOException {
-        statsOut.stats.clear();
+        statsOut.packageStats.clear();
         statsOut.configurations.clear();
         statsOut.activeConfiguration = null;
 
@@ -179,7 +191,6 @@
             statsOut.events.clear();
         }
 
-        statsOut.beginTime = XmlUtils.readLongAttribute(parser, BEGIN_TIME_ATTR);
         statsOut.endTime = XmlUtils.readLongAttribute(parser, END_TIME_ATTR);
 
         int eventCode;
@@ -196,11 +207,11 @@
                     loadUsageStats(parser, statsOut);
                     break;
 
-                case CONFIGURATION_TAG:
+                case CONFIG_TAG:
                     loadConfigStats(parser, statsOut);
                     break;
 
-                case EVENT_LOG_TAG:
+                case EVENT_TAG:
                     loadEvent(parser, statsOut);
                     break;
             }
@@ -208,32 +219,38 @@
     }
 
     /**
-     * Writes the stats object to an XML file. The {@link FastXmlSerializer}
+     * Writes the stats object to an XML file. The {@link XmlSerializer}
      * has already written the <code><usagestats></code> tag, but attributes may still
      * be added.
      *
-     * @param serializer The serializer to which to write the stats data.
+     * @param xml The serializer to which to write the packageStats data.
      * @param stats The stats object to write to the XML file.
      */
-    public static void write(FastXmlSerializer serializer, IntervalStats stats) throws IOException {
-        serializer.attribute(null, BEGIN_TIME_ATTR, Long.toString(stats.beginTime));
-        serializer.attribute(null, END_TIME_ATTR, Long.toString(stats.endTime));
+    public static void write(XmlSerializer xml, IntervalStats stats) throws IOException {
+        XmlUtils.writeLongAttribute(xml, END_TIME_ATTR, stats.endTime - stats.beginTime);
 
-        final int statsCount = stats.stats.size();
+        xml.startTag(null, PACKAGES_TAG);
+        final int statsCount = stats.packageStats.size();
         for (int i = 0; i < statsCount; i++) {
-            writeUsageStats(serializer, stats.stats.valueAt(i));
+            writeUsageStats(xml, stats, stats.packageStats.valueAt(i));
         }
+        xml.endTag(null, PACKAGES_TAG);
 
+
+        xml.startTag(null, CONFIGURATIONS_TAG);
         final int configCount = stats.configurations.size();
         for (int i = 0; i < configCount; i++) {
             boolean active = stats.activeConfiguration.equals(stats.configurations.keyAt(i));
-            writeConfigStats(serializer, stats.configurations.valueAt(i), active);
+            writeConfigStats(xml, stats, stats.configurations.valueAt(i), active);
         }
+        xml.endTag(null, CONFIGURATIONS_TAG);
 
+        xml.startTag(null, EVENT_LOG_TAG);
         final int eventCount = stats.events != null ? stats.events.size() : 0;
         for (int i = 0; i < eventCount; i++) {
-            writeEvent(serializer, stats.events.valueAt(i));
+            writeEvent(xml, stats, stats.events.valueAt(i));
         }
+        xml.endTag(null, EVENT_LOG_TAG);
     }
 
     private UsageStatsXmlV1() {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 7142a99..2769666 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -32,7 +32,6 @@
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Calendar;
 import java.util.List;
 
 /**
@@ -47,7 +46,7 @@
     private final UsageStatsDatabase mDatabase;
     private final IntervalStats[] mCurrentStats;
     private boolean mStatsChanged = false;
-    private final Calendar mDailyExpiryDate;
+    private final UnixCalendar mDailyExpiryDate;
     private final StatsUpdatedListener mListener;
     private final String mLogPrefix;
 
@@ -56,7 +55,7 @@
     }
 
     UserUsageStatsService(int userId, File usageStatsDir, StatsUpdatedListener listener) {
-        mDailyExpiryDate = Calendar.getInstance();
+        mDailyExpiryDate = new UnixCalendar(0);
         mDatabase = new UsageStatsDatabase(usageStatsDir);
         mCurrentStats = new IntervalStats[UsageStatsManager.INTERVAL_COUNT];
         mListener = listener;
@@ -66,6 +65,7 @@
     void init() {
         mDatabase.init();
 
+        final long timeNow = System.currentTimeMillis();
         int nullCount = 0;
         for (int i = 0; i < mCurrentStats.length; i++) {
             mCurrentStats[i] = mDatabase.getLatestUsageStats(i);
@@ -73,6 +73,11 @@
                 // Find out how many intervals we don't have data for.
                 // Ideally it should be all or none.
                 nullCount++;
+            } else if (mCurrentStats[i].beginTime > timeNow) {
+                Slog.e(TAG, mLogPrefix + "Interval " + i + " has stat in the future " +
+                        mCurrentStats[i].beginTime);
+                mCurrentStats[i] = null;
+                nullCount++;
             }
         }
 
@@ -94,17 +99,18 @@
             // that is reported.
             mDailyExpiryDate.setTimeInMillis(
                     mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime);
-            mDailyExpiryDate.add(Calendar.DAY_OF_YEAR, 1);
-            UsageStatsUtils.truncateDateTo(UsageStatsManager.INTERVAL_DAILY, mDailyExpiryDate);
-            Slog.i(TAG, mLogPrefix + "Rollover scheduled for "
-                    + sDateFormat.format(mDailyExpiryDate.getTime()));
+            mDailyExpiryDate.addDays(1);
+            mDailyExpiryDate.truncateToDay();
+            Slog.i(TAG, mLogPrefix + "Rollover scheduled @ " +
+                    sDateFormat.format(mDailyExpiryDate.getTimeInMillis()) +
+                    "(" + mDailyExpiryDate.getTimeInMillis() + ")");
         }
 
         // Now close off any events that were open at the time this was saved.
         for (IntervalStats stat : mCurrentStats) {
-            final int pkgCount = stat.stats.size();
+            final int pkgCount = stat.packageStats.size();
             for (int i = 0; i < pkgCount; i++) {
-                UsageStats pkgStats = stat.stats.valueAt(i);
+                UsageStats pkgStats = stat.packageStats.valueAt(i);
                 if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
                         pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
                     stat.update(pkgStats.mPackageName, stat.lastTimeSaved,
@@ -162,13 +168,13 @@
                 public void combine(IntervalStats stats, boolean mutable,
                         List<UsageStats> accResult) {
                     if (!mutable) {
-                        accResult.addAll(stats.stats.values());
+                        accResult.addAll(stats.packageStats.values());
                         return;
                     }
 
-                    final int statCount = stats.stats.size();
+                    final int statCount = stats.packageStats.size();
                     for (int i = 0; i < statCount; i++) {
-                        accResult.add(new UsageStats(stats.stats.valueAt(i)));
+                        accResult.add(new UsageStats(stats.packageStats.valueAt(i)));
                     }
                 }
             };
@@ -195,49 +201,68 @@
      * and bucket, then calls the {@link com.android.server.usage.UsageStatsDatabase.StatCombiner}
      * provided to select the stats to use from the IntervalStats object.
      */
-    private <T> List<T> queryStats(int bucketType, long beginTime, long endTime,
+    private <T> List<T> queryStats(int intervalType, final long beginTime, final long endTime,
             StatCombiner<T> combiner) {
-        if (bucketType == UsageStatsManager.INTERVAL_BEST) {
-            bucketType = mDatabase.findBestFitBucket(beginTime, endTime);
+        if (intervalType == UsageStatsManager.INTERVAL_BEST) {
+            intervalType = mDatabase.findBestFitBucket(beginTime, endTime);
+            if (intervalType < 0) {
+                // Nothing saved to disk yet, so every stat is just as equal (no rollover has
+                // occurred.
+                intervalType = UsageStatsManager.INTERVAL_DAILY;
+            }
         }
 
-        if (bucketType < 0 || bucketType >= mCurrentStats.length) {
+        if (intervalType < 0 || intervalType >= mCurrentStats.length) {
             if (DEBUG) {
-                Slog.d(TAG, mLogPrefix + "Bad bucketType used " + bucketType);
+                Slog.d(TAG, mLogPrefix + "Bad intervalType used " + intervalType);
             }
             return null;
         }
 
-        if (beginTime >= mCurrentStats[bucketType].endTime) {
-            if (DEBUG) {
-                Slog.d(TAG, mLogPrefix + "Requesting stats after " + beginTime + " but latest is "
-                        + mCurrentStats[bucketType].endTime);
-            }
-            // Nothing newer available.
-            return null;
-
-        } else if (beginTime >= mCurrentStats[bucketType].beginTime) {
-            if (DEBUG) {
-                Slog.d(TAG, mLogPrefix + "Returning in-memory stats for bucket " + bucketType);
-            }
-            // Fast path for retrieving in-memory state.
-            ArrayList<T> results = new ArrayList<>();
-            combiner.combine(mCurrentStats[bucketType], true, results);
-            return results;
-        }
-
-        // Flush any changes that were made to disk before we do a disk query.
-        // If we're not grabbing the ongoing stats, no need to persist.
-        persistActiveStats();
+        final IntervalStats currentStats = mCurrentStats[intervalType];
 
         if (DEBUG) {
-            Slog.d(TAG, mLogPrefix + "SELECT * FROM " + bucketType + " WHERE beginTime >= "
+            Slog.d(TAG, mLogPrefix + "SELECT * FROM " + intervalType + " WHERE beginTime >= "
                     + beginTime + " AND endTime < " + endTime);
         }
 
-        final List<T> results = mDatabase.queryUsageStats(bucketType, beginTime, endTime, combiner);
+        if (beginTime >= currentStats.endTime) {
+            if (DEBUG) {
+                Slog.d(TAG, mLogPrefix + "Requesting stats after " + beginTime + " but latest is "
+                        + currentStats.endTime);
+            }
+            // Nothing newer available.
+            return null;
+        }
+
+        // Truncate the endTime to just before the in-memory stats. Then, we'll append the
+        // in-memory stats to the results (if necessary) so as to avoid writing to disk too
+        // often.
+        final long truncatedEndTime = Math.min(currentStats.beginTime, endTime);
+
+        // Get the stats from disk.
+        List<T> results = mDatabase.queryUsageStats(intervalType, beginTime,
+                truncatedEndTime, combiner);
         if (DEBUG) {
-            Slog.d(TAG, mLogPrefix + "Results: " + (results == null ? 0 : results.size()));
+            Slog.d(TAG, "Got " + (results != null ? results.size() : 0) + " results from disk");
+            Slog.d(TAG, "Current stats beginTime=" + currentStats.beginTime +
+                    " endTime=" + currentStats.endTime);
+        }
+
+        // Now check if the in-memory stats match the range and add them if they do.
+        if (beginTime < currentStats.endTime && endTime > currentStats.beginTime) {
+            if (DEBUG) {
+                Slog.d(TAG, mLogPrefix + "Returning in-memory stats");
+            }
+
+            if (results == null) {
+                results = new ArrayList<>();
+            }
+            combiner.combine(currentStats, true, results);
+        }
+
+        if (DEBUG) {
+            Slog.d(TAG, mLogPrefix + "Results: " + (results != null ? results.size() : 0));
         }
         return results;
     }
@@ -250,44 +275,45 @@
         return queryStats(bucketType, beginTime, endTime, sConfigStatsCombiner);
     }
 
-    UsageEvents queryEvents(long beginTime, long endTime) {
-        if (endTime > mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime) {
-            if (beginTime > mCurrentStats[UsageStatsManager.INTERVAL_DAILY].endTime) {
-                return null;
-            }
+    UsageEvents queryEvents(final long beginTime, final long endTime) {
+        final ArraySet<String> names = new ArraySet<>();
+        List<UsageEvents.Event> results = queryStats(UsageStatsManager.INTERVAL_DAILY,
+                beginTime, endTime, new StatCombiner<UsageEvents.Event>() {
+                    @Override
+                    public void combine(IntervalStats stats, boolean mutable,
+                            List<UsageEvents.Event> accumulatedResult) {
+                        if (stats.events == null) {
+                            return;
+                        }
 
-            TimeSparseArray<UsageEvents.Event> events =
-                    mCurrentStats[UsageStatsManager.INTERVAL_DAILY].events;
-            if (events == null) {
-                return null;
-            }
+                        final int startIndex = stats.events.closestIndexOnOrAfter(beginTime);
+                        if (startIndex < 0) {
+                            return;
+                        }
 
-            final int startIndex = events.closestIndexOnOrAfter(beginTime);
-            if (startIndex < 0) {
-                return null;
-            }
+                        final int size = stats.events.size();
+                        for (int i = startIndex; i < size; i++) {
+                            if (stats.events.keyAt(i) >= endTime) {
+                                return;
+                            }
 
-            ArraySet<String> names = new ArraySet<>();
-            ArrayList<UsageEvents.Event> results = new ArrayList<>();
-            final int size = events.size();
-            for (int i = startIndex; i < size; i++) {
-                if (events.keyAt(i) >= endTime) {
-                    break;
-                }
-                final UsageEvents.Event event = events.valueAt(i);
-                names.add(event.mPackage);
-                if (event.mClass != null) {
-                    names.add(event.mClass);
-                }
-                results.add(event);
-            }
-            String[] table = names.toArray(new String[names.size()]);
-            Arrays.sort(table);
-            return new UsageEvents(results, table);
+                            final UsageEvents.Event event = stats.events.valueAt(i);
+                            names.add(event.mPackage);
+                            if (event.mClass != null) {
+                                names.add(event.mClass);
+                            }
+                            accumulatedResult.add(event);
+                        }
+                    }
+                });
+
+        if (results == null || results.isEmpty()) {
+            return null;
         }
 
-        // TODO(adamlesinski): Query the previous days.
-        return null;
+        String[] table = names.toArray(new String[names.size()]);
+        Arrays.sort(table);
+        return new UsageEvents(results, table);
     }
 
     void persistActiveStats() {
@@ -314,9 +340,9 @@
                 mCurrentStats[UsageStatsManager.INTERVAL_DAILY].activeConfiguration;
         ArraySet<String> continuePreviousDay = new ArraySet<>();
         for (IntervalStats stat : mCurrentStats) {
-            final int pkgCount = stat.stats.size();
+            final int pkgCount = stat.packageStats.size();
             for (int i = 0; i < pkgCount; i++) {
-                UsageStats pkgStats = stat.stats.valueAt(i);
+                UsageStats pkgStats = stat.packageStats.valueAt(i);
                 if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
                         pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
                     continuePreviousDay.add(pkgStats.mPackageName);
@@ -360,54 +386,53 @@
     private void loadActiveStats() {
         final long timeNow = System.currentTimeMillis();
 
-        Calendar tempCal = mDailyExpiryDate;
-        for (int bucketType = 0; bucketType < mCurrentStats.length; bucketType++) {
+        final UnixCalendar tempCal = mDailyExpiryDate;
+        for (int intervalType = 0; intervalType < mCurrentStats.length; intervalType++) {
             tempCal.setTimeInMillis(timeNow);
-            UsageStatsUtils.truncateDateTo(bucketType, tempCal);
+            UnixCalendar.truncateTo(tempCal, intervalType);
 
-            if (mCurrentStats[bucketType] != null &&
-                    mCurrentStats[bucketType].beginTime == tempCal.getTimeInMillis()) {
+            if (mCurrentStats[intervalType] != null &&
+                    mCurrentStats[intervalType].beginTime == tempCal.getTimeInMillis()) {
                 // These are the same, no need to load them (in memory stats are always newer
                 // than persisted stats).
                 continue;
             }
 
-            final long lastBeginTime = mDatabase.getLatestUsageStatsBeginTime(bucketType);
-            if (lastBeginTime >= tempCal.getTimeInMillis()) {
+            final long lastBeginTime = mDatabase.getLatestUsageStatsBeginTime(intervalType);
+            if (lastBeginTime > timeNow) {
+                Slog.e(TAG, mLogPrefix + "Latest usage stats for interval " +
+                        intervalType + " begins in the future");
+                mCurrentStats[intervalType] = null;
+            } else if (lastBeginTime >= tempCal.getTimeInMillis()) {
                 if (DEBUG) {
-                    Slog.d(TAG, mLogPrefix + "Loading existing stats (" + lastBeginTime +
-                            ") for bucket " + bucketType);
+                    Slog.d(TAG, mLogPrefix + "Loading existing stats @ " +
+                            sDateFormat.format(lastBeginTime) + "(" + lastBeginTime +
+                            ") for interval " + intervalType);
                 }
-                mCurrentStats[bucketType] = mDatabase.getLatestUsageStats(bucketType);
-                if (DEBUG) {
-                    if (mCurrentStats[bucketType] != null) {
-                        Slog.d(TAG, mLogPrefix + "Found " +
-                                (mCurrentStats[bucketType].events == null ?
-                                        0 : mCurrentStats[bucketType].events.size()) +
-                                " events");
-                    }
-                }
+                mCurrentStats[intervalType] = mDatabase.getLatestUsageStats(intervalType);
             } else {
-                mCurrentStats[bucketType] = null;
+                mCurrentStats[intervalType] = null;
             }
 
-            if (mCurrentStats[bucketType] == null) {
+            if (mCurrentStats[intervalType] == null) {
                 if (DEBUG) {
-                    Slog.d(TAG, "Creating new stats (" + tempCal.getTimeInMillis() +
-                            ") for bucket " + bucketType);
+                    Slog.d(TAG, "Creating new stats @ " +
+                            sDateFormat.format(tempCal.getTimeInMillis()) + "(" +
+                            tempCal.getTimeInMillis() + ") for interval " + intervalType);
 
                 }
-                mCurrentStats[bucketType] = new IntervalStats();
-                mCurrentStats[bucketType].beginTime = tempCal.getTimeInMillis();
-                mCurrentStats[bucketType].endTime = timeNow;
+                mCurrentStats[intervalType] = new IntervalStats();
+                mCurrentStats[intervalType].beginTime = tempCal.getTimeInMillis();
+                mCurrentStats[intervalType].endTime = timeNow;
             }
         }
         mStatsChanged = false;
         mDailyExpiryDate.setTimeInMillis(timeNow);
-        mDailyExpiryDate.add(Calendar.DAY_OF_YEAR, 1);
-        UsageStatsUtils.truncateDateTo(UsageStatsManager.INTERVAL_DAILY, mDailyExpiryDate);
-        Slog.i(TAG, mLogPrefix + "Rollover scheduled for "
-                + sDateFormat.format(mDailyExpiryDate.getTime()));
+        mDailyExpiryDate.addDays(1);
+        mDailyExpiryDate.truncateToDay();
+        Slog.i(TAG, mLogPrefix + "Rollover scheduled @ " +
+                sDateFormat.format(mDailyExpiryDate.getTimeInMillis()) + "(" +
+                tempCal.getTimeInMillis() + ")");
     }
 
 
diff --git a/telecomm/java/android/telecomm/AudioState.java b/telecomm/java/android/telecomm/AudioState.java
index a5fda79..314704b 100644
--- a/telecomm/java/android/telecomm/AudioState.java
+++ b/telecomm/java/android/telecomm/AudioState.java
@@ -34,7 +34,7 @@
     /** Direct the audio stream through a wired headset. */
     public static final int ROUTE_WIRED_HEADSET = 0x00000004;
 
-    /** Direct the audio stream through the device's spakerphone. */
+    /** Direct the audio stream through the device's speakerphone. */
     public static final int ROUTE_SPEAKER       = 0x00000008;
 
     /**
@@ -43,7 +43,10 @@
      */
     public static final int ROUTE_WIRED_OR_EARPIECE = ROUTE_EARPIECE | ROUTE_WIRED_HEADSET;
 
-    /** Bit mask of all possible audio routes. */
+    /** Bit mask of all possible audio routes.
+     *
+     * @hide
+     */
     public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
             ROUTE_SPEAKER;
 
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
index 5bf0855..c3aa2a0 100644
--- a/telecomm/java/android/telecomm/Call.java
+++ b/telecomm/java/android/telecomm/Call.java
@@ -517,6 +517,20 @@
     }
 
     /**
+     * Merges the calls within this conference. See {@link PhoneCapabilities#MERGE_CONFERENCE}.
+     */
+    public void mergeConference() {
+        mInCallAdapter.mergeConference(mTelecommCallId);
+    }
+
+    /**
+     * Swaps the calls within this conference. See {@link PhoneCapabilities#SWAP_CONFERENCE}.
+     */
+    public void swapConference() {
+        mInCallAdapter.swapConference(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
diff --git a/telecomm/java/android/telecomm/Conference.java b/telecomm/java/android/telecomm/Conference.java
index 879ff66..f9c3ac3 100644
--- a/telecomm/java/android/telecomm/Conference.java
+++ b/telecomm/java/android/telecomm/Conference.java
@@ -54,7 +54,7 @@
         mPhoneAccount = phoneAccount;
     }
 
-    public final PhoneAccountHandle getPhoneAccount() {
+    public final PhoneAccountHandle getPhoneAccountHandle() {
         return mPhoneAccount;
     }
 
@@ -93,6 +93,18 @@
     public void onUnhold() {}
 
     /**
+     * Invoked when the child calls should be merged. Only invoked if the conference contains the
+     * capability {@link PhoneCapabilities#MERGE_CONFERENCE}.
+     */
+    public void onMerge() {}
+
+    /**
+     * Invoked when the child calls should be swapped. Only invoked if the conference contains the
+     * capability {@link PhoneCapabilities#SWAP_CONFERENCE}.
+     */
+    public void onSwap() {}
+
+    /**
      * Sets state to be on hold.
      */
     public final void setOnHold() {
@@ -141,7 +153,7 @@
      * @param connection The connection to add.
      * @return True if the connection was successfully added.
      */
-    public boolean addConnection(Connection connection) {
+    public final boolean addConnection(Connection connection) {
         if (connection != null && !mChildConnections.contains(connection)) {
             if (connection.setConference(this)) {
                 mChildConnections.add(connection);
@@ -160,7 +172,7 @@
      * @param connection The connection to remove.
      * @return True if the connection was successfully removed.
      */
-    public void removeConnection(Connection connection) {
+    public final void removeConnection(Connection connection) {
         Log.d(this, "removing %s from %s", connection, mChildConnections);
         if (connection != null && mChildConnections.remove(connection)) {
             connection.resetConference();
@@ -171,9 +183,9 @@
     }
 
     /**
-     * Tears down the conference object and any of it's current connections.
+     * Tears down the conference object and any of its current connections.
      */
-    public void destroy() {
+    public final void destroy() {
         Log.d(this, "destroying conference : %s", this);
         // Tear down the children.
         for (Connection connection : mChildConnections) {
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index 4d6e267..6df117e 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -1068,10 +1068,10 @@
         if (mState != state) {
             Log.d(this, "setState: %s", stateToString(state));
             mState = state;
+            onSetState(state);
             for (Listener l : mListeners) {
                 l.onStateChanged(this, state);
             }
-            onSetState(state);
         }
     }
 
diff --git a/telecomm/java/android/telecomm/ConnectionRequest.java b/telecomm/java/android/telecomm/ConnectionRequest.java
index 39ae59a..d5a6aa5 100644
--- a/telecomm/java/android/telecomm/ConnectionRequest.java
+++ b/telecomm/java/android/telecomm/ConnectionRequest.java
@@ -29,31 +29,25 @@
 
     // TODO: Token to limit recursive invocations
     private final PhoneAccountHandle mAccountHandle;
-    private final Uri mHandle;
-    private final int mHandlePresentation;
+    private final Uri mAddress;
     private final Bundle mExtras;
     private final int mVideoState;
 
     /**
      * @param accountHandle The accountHandle which should be used to place the call.
      * @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect.
-     * @param handlePresentation The {@link PropertyPresentation} which controls how the handle
-     *         is shown.
      * @param extras Application-specific extra data.
      */
     public ConnectionRequest(
             PhoneAccountHandle accountHandle,
             Uri handle,
-            int handlePresentation,
             Bundle extras) {
-        this(accountHandle, handle, handlePresentation, extras, VideoProfile.VideoState.AUDIO_ONLY);
+        this(accountHandle, handle, extras, VideoProfile.VideoState.AUDIO_ONLY);
     }
 
     /**
      * @param accountHandle The accountHandle which should be used to place the call.
      * @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect.
-     * @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.
      * @hide
@@ -61,20 +55,17 @@
     public ConnectionRequest(
             PhoneAccountHandle accountHandle,
             Uri handle,
-            int handlePresentation,
             Bundle extras,
             int videoState) {
         mAccountHandle = accountHandle;
-        mHandle = handle;
-        mHandlePresentation = handlePresentation;
+        mAddress = handle;
         mExtras = extras;
         mVideoState = videoState;
     }
 
     private ConnectionRequest(Parcel in) {
         mAccountHandle = in.readParcelable(getClass().getClassLoader());
-        mHandle = in.readParcelable(getClass().getClassLoader());
-        mHandlePresentation = in.readInt();
+        mAddress = in.readParcelable(getClass().getClassLoader());
         mExtras = in.readParcelable(getClass().getClassLoader());
         mVideoState = in.readInt();
     }
@@ -87,12 +78,7 @@
     /**
      * The handle (e.g., phone number) to which the {@link Connection} is to connect.
      */
-    public Uri getHandle() { return mHandle; }
-
-    /**
-     * The {@link PropertyPresentation} which controls how the handle is shown.
-     */
-    public int getHandlePresentation() { return mHandlePresentation; }
+    public Uri getAddress() { return mAddress; }
 
     /**
      * Application-specific extra data. Used for passing back information from an incoming
@@ -118,9 +104,9 @@
     @Override
     public String toString() {
         return String.format("ConnectionRequest %s %s",
-                mHandle == null
+                mAddress == null
                         ? Uri.EMPTY
-                        : Connection.toLogSafePhoneNumber(mHandle.toString()),
+                        : Connection.toLogSafePhoneNumber(mAddress.toString()),
                 mExtras == null ? "" : mExtras);
     }
 
@@ -147,8 +133,7 @@
     @Override
     public void writeToParcel(Parcel destination, int flags) {
         destination.writeParcelable(mAccountHandle, 0);
-        destination.writeParcelable(mHandle, 0);
-        destination.writeInt(mHandlePresentation);
+        destination.writeParcelable(mAddress, 0);
         destination.writeParcelable(mExtras, 0);
         destination.writeInt(mVideoState);
     }
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 2dc6910..39365b6 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -72,6 +72,8 @@
     private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 15;
     private static final int MSG_REMOVE_CONNECTION_SERVICE_ADAPTER = 16;
     private static final int MSG_ANSWER_VIDEO = 17;
+    private static final int MSG_MERGE_CONFERENCE = 18;
+    private static final int MSG_SWAP_CONFERENCE = 19;
 
     private static Connection sNullConnection;
 
@@ -182,6 +184,16 @@
         }
 
         @Override
+        public void mergeConference(String callId) {
+            mHandler.obtainMessage(MSG_MERGE_CONFERENCE, callId).sendToTarget();
+        }
+
+        @Override
+        public void swapConference(String callId) {
+            mHandler.obtainMessage(MSG_SWAP_CONFERENCE, callId).sendToTarget();
+        }
+
+        @Override
         public void onPostDialContinue(String callId, boolean proceed) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = callId;
@@ -298,6 +310,12 @@
                 case MSG_SPLIT_FROM_CONFERENCE:
                     splitFromConference((String) msg.obj);
                     break;
+                case MSG_MERGE_CONFERENCE:
+                    mergeConference((String) msg.obj);
+                    break;
+                case MSG_SWAP_CONFERENCE:
+                    swapConference((String) msg.obj);
+                    break;
                 case MSG_ON_POST_DIAL_CONTINUE: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
@@ -639,6 +657,22 @@
         }
     }
 
+    private void mergeConference(String callId) {
+        Log.d(this, "mergeConference(%s)", callId);
+        Conference conference = findConferenceForAction(callId, "mergeConference");
+        if (conference != null) {
+            conference.onMerge();
+        }
+    }
+
+    private void swapConference(String callId) {
+        Log.d(this, "swapConference(%s)", callId);
+        Conference conference = findConferenceForAction(callId, "swapConference");
+        if (conference != null) {
+            conference.onSwap();
+        }
+    }
+
     private void onPostDialContinue(String callId, boolean proceed) {
         Log.d(this, "onPostDialContinue(%s)", callId);
         findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
@@ -747,7 +781,7 @@
                 }
             }
             ParcelableConference parcelableConference = new ParcelableConference(
-                    conference.getPhoneAccount(),
+                    conference.getPhoneAccountHandle(),
                     conference.getState(),
                     conference.getCapabilities(),
                     connectionIds);
diff --git a/telecomm/java/android/telecomm/InCallAdapter.java b/telecomm/java/android/telecomm/InCallAdapter.java
index 80f7b57..96ea5a6 100644
--- a/telecomm/java/android/telecomm/InCallAdapter.java
+++ b/telecomm/java/android/telecomm/InCallAdapter.java
@@ -241,6 +241,26 @@
     }
 
     /**
+     * Instructs Telecomm to merge child calls of the specified conference call.
+     */
+    public void mergeConference(String callId) {
+        try {
+            mAdapter.mergeConference(callId);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * Instructs Telecomm to swap the child calls of the specified conference call.
+     */
+    public void swapConference(String callId) {
+        try {
+            mAdapter.swapConference(callId);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
      * Instructs Telecomm to turn the proximity sensor on.
      */
     public void turnProximitySensorOn() {
diff --git a/telecomm/java/android/telecomm/PhoneCapabilities.java b/telecomm/java/android/telecomm/PhoneCapabilities.java
index 3d76608..7a338b4 100644
--- a/telecomm/java/android/telecomm/PhoneCapabilities.java
+++ b/telecomm/java/android/telecomm/PhoneCapabilities.java
@@ -27,11 +27,17 @@
     /** Call supports the hold feature. */
     public static final int SUPPORT_HOLD       = 0x00000002;
 
-    /** Call can currently be merged. */
-    public static final int MERGE_CALLS        = 0x00000004;
+    /**
+     * Calls within a conference can be merged. Some connection services create a conference call
+     * only after two calls have been merged.  However, a conference call can also be added the
+     * moment there are more than one call. CDMA calls are implemented in this way because the call
+     * actions are more limited when more than one call exists. This flag allows merge to be exposed
+     * as a capability on the conference call instead of individual calls.
+     */
+    public static final int MERGE_CONFERENCE   = 0x00000004;
 
-    /** Call can currently be swapped with another call. */
-    public static final int SWAP_CALLS         = 0x00000008;
+    /** Calls withing a conference can be swapped between foreground and background. */
+    public static final int SWAP_CONFERENCE    = 0x00000008;
 
     /** Call currently supports adding another call to this one. */
     public static final int ADD_CALL           = 0x00000010;
@@ -42,8 +48,11 @@
     /** Call can be muted. */
     public static final int MUTE               = 0x00000040;
 
-    /** Call supports generic conference mode. */
-    public static final int GENERIC_CONFERENCE = 0x00000080;
+    /**
+     * Call supports conference call management. This capability only applies to conference calls
+     * which can have other calls as children.
+     */
+    public static final int MANAGE_CONFERENCE = 0x00000080;
 
     /**
      * Local device supports video telephony.
@@ -69,8 +78,8 @@
      */
     public static final int VoWIFI = 0x00000800;
 
-    public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CALLS | SWAP_CALLS | ADD_CALL
-            | RESPOND_VIA_TEXT | MUTE | GENERIC_CONFERENCE;
+    public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CONFERENCE | SWAP_CONFERENCE | ADD_CALL
+            | RESPOND_VIA_TEXT | MUTE | MANAGE_CONFERENCE;
 
     public static String toString(int capabilities) {
         StringBuilder builder = new StringBuilder();
@@ -81,11 +90,11 @@
         if ((capabilities & SUPPORT_HOLD) != 0) {
             builder.append(" SUPPORT_HOLD");
         }
-        if ((capabilities & MERGE_CALLS) != 0) {
-            builder.append(" MERGE_CALLS");
+        if ((capabilities & MERGE_CONFERENCE) != 0) {
+            builder.append(" MERGE_CONFERENCE");
         }
-        if ((capabilities & SWAP_CALLS) != 0) {
-            builder.append(" SWAP_CALLS");
+        if ((capabilities & SWAP_CONFERENCE) != 0) {
+            builder.append(" SWAP_CONFERENCE");
         }
         if ((capabilities & ADD_CALL) != 0) {
             builder.append(" ADD_CALL");
@@ -96,8 +105,8 @@
         if ((capabilities & MUTE) != 0) {
             builder.append(" MUTE");
         }
-        if ((capabilities & GENERIC_CONFERENCE) != 0) {
-            builder.append(" GENERIC_CONFERENCE");
+        if ((capabilities & MANAGE_CONFERENCE) != 0) {
+            builder.append(" MANAGE_CONFERENCE");
         }
         if ((capabilities & SUPPORTS_VT_LOCAL) != 0) {
             builder.append(" SUPPORTS_VT_LOCAL");
diff --git a/telecomm/java/android/telecomm/RemoteConference.java b/telecomm/java/android/telecomm/RemoteConference.java
index 02f6de6..b073827 100644
--- a/telecomm/java/android/telecomm/RemoteConference.java
+++ b/telecomm/java/android/telecomm/RemoteConference.java
@@ -32,7 +32,7 @@
  */
 public final class RemoteConference {
 
-    public abstract static class Listener {
+    public abstract static class Callback {
         public void onStateChanged(RemoteConference conference, int oldState, int newState) {}
         public void onDisconnected(RemoteConference conference, int cause, String message) {}
         public void onConnectionAdded(RemoteConference conference, RemoteConnection connection) {}
@@ -44,7 +44,7 @@
     private final String mId;
     private final IConnectionService mConnectionService;
 
-    private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
+    private final Set<Callback> mCallbacks = new CopyOnWriteArraySet<>();
     private final List<RemoteConnection> mChildConnections = new CopyOnWriteArrayList<>();
     private final List<RemoteConnection> mUnmodifiableChildConnections =
             Collections.unmodifiableList(mChildConnections);
@@ -70,8 +70,8 @@
         for (RemoteConnection connection : mChildConnections) {
             connection.setConference(null);
         }
-        for (Listener l : mListeners) {
-            l.onDestroyed(this);
+        for (Callback c : mCallbacks) {
+            c.onDestroyed(this);
         }
     }
 
@@ -88,8 +88,8 @@
         if (mState != newState) {
             int oldState = mState;
             mState = newState;
-            for (Listener l : mListeners) {
-                l.onStateChanged(this, oldState, newState);
+            for (Callback c : mCallbacks) {
+                c.onStateChanged(this, oldState, newState);
             }
         }
     }
@@ -99,8 +99,8 @@
         if (!mChildConnections.contains(connection)) {
             mChildConnections.add(connection);
             connection.setConference(this);
-            for (Listener l : mListeners) {
-                l.onConnectionAdded(this, connection);
+            for (Callback c : mCallbacks) {
+                c.onConnectionAdded(this, connection);
             }
         }
     }
@@ -110,8 +110,8 @@
         if (mChildConnections.contains(connection)) {
             mChildConnections.remove(connection);
             connection.setConference(null);
-            for (Listener l : mListeners) {
-                l.onConnectionRemoved(this, connection);
+            for (Callback c : mCallbacks) {
+                c.onConnectionRemoved(this, connection);
             }
         }
     }
@@ -120,8 +120,8 @@
     void setCallCapabilities(int capabilities) {
         if (mCallCapabilities != capabilities) {
             mCallCapabilities = capabilities;
-            for (Listener l : mListeners) {
-                l.onCapabilitiesChanged(this, mCallCapabilities);
+            for (Callback c : mCallbacks) {
+                c.onCapabilitiesChanged(this, mCallCapabilities);
             }
         }
     }
@@ -132,8 +132,8 @@
             mDisconnectCause = cause;
             mDisconnectMessage = message;
             setState(Connection.STATE_DISCONNECTED);
-            for (Listener l : mListeners) {
-                l.onDisconnected(this, cause, message);
+            for (Callback c : mCallbacks) {
+                c.onDisconnected(this, cause, message);
             }
         }
     }
@@ -188,11 +188,11 @@
         return mDisconnectMessage;
     }
 
-    public final void addListener(Listener listener) {
-        mListeners.add(listener);
+    public final void addCallback(Callback callback) {
+        mCallbacks.add(callback);
     }
 
-    public final void removeListener(Listener listener) {
-        mListeners.remove(listener);
+    public final void removeCallback(Callback callback) {
+        mCallbacks.remove(callback);
     }
 }
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 0b6badb..8ad0ad0 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -191,7 +191,7 @@
             conference.setState(parcel.getState());
             conference.setCallCapabilities(parcel.getCapabilities());
             mConferenceById.put(callId, conference);
-            conference.addListener(new RemoteConference.Listener() {
+            conference.addCallback(new RemoteConference.Callback() {
                 @Override
                 public void onDestroyed(RemoteConference c) {
                     mConferenceById.remove(callId);
@@ -325,8 +325,7 @@
         final String id = UUID.randomUUID().toString();
         final ConnectionRequest newRequest = new ConnectionRequest(
                 request.getAccountHandle(),
-                request.getHandle(),
-                request.getHandlePresentation(),
+                request.getAddress(),
                 request.getExtras(),
                 request.getVideoState());
         try {
diff --git a/telecomm/java/android/telecomm/StatusHints.java b/telecomm/java/android/telecomm/StatusHints.java
index f7c4f2f..ff96a5b 100644
--- a/telecomm/java/android/telecomm/StatusHints.java
+++ b/telecomm/java/android/telecomm/StatusHints.java
@@ -32,23 +32,24 @@
  */
 public final class StatusHints implements Parcelable {
 
-    private final ComponentName mComponentName;
+    private final ComponentName mPackageName;
     private final CharSequence mLabel;
     private final int mIconResId;
     private final Bundle mExtras;
 
-    public StatusHints(ComponentName componentName, CharSequence label, int iconResId, Bundle extras) {
-        mComponentName = componentName;
+    public StatusHints(ComponentName packageName, CharSequence label, int iconResId,
+            Bundle extras) {
+        mPackageName = packageName;
         mLabel = label;
         mIconResId = iconResId;
         mExtras = extras;
     }
 
     /**
-     * @return A component used to load the icon.
+     * @return A package used to load the icon.
      */
-    public ComponentName getComponentName() {
-        return mComponentName;
+    public ComponentName getPackageName() {
+        return mPackageName;
     }
 
     /**
@@ -88,7 +89,7 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
-        out.writeParcelable(mComponentName, flags);
+        out.writeParcelable(mPackageName, flags);
         out.writeCharSequence(mLabel);
         out.writeInt(mIconResId);
         out.writeParcelable(mExtras, 0);
@@ -106,7 +107,7 @@
     };
 
     private StatusHints(Parcel in) {
-        mComponentName = in.readParcelable(getClass().getClassLoader());
+        mPackageName = in.readParcelable(getClass().getClassLoader());
         mLabel = in.readCharSequence();
         mIconResId = in.readInt();
         mExtras = in.readParcelable(getClass().getClassLoader());
@@ -115,16 +116,16 @@
     private Drawable getIcon(Context context, int resId) {
         Context packageContext;
         try {
-            packageContext = context.createPackageContext(mComponentName.getPackageName(), 0);
+            packageContext = context.createPackageContext(mPackageName.getPackageName(), 0);
         } catch (PackageManager.NameNotFoundException e) {
-            Log.e(this, e, "Cannot find package %s", mComponentName.getPackageName());
+            Log.e(this, e, "Cannot find package %s", mPackageName.getPackageName());
             return null;
         }
         try {
             return packageContext.getDrawable(resId);
         } catch (MissingResourceException e) {
             Log.e(this, e, "Cannot find icon %d in package %s",
-                    resId, mComponentName.getPackageName());
+                    resId, mPackageName.getPackageName());
             return null;
         }
     }
@@ -133,7 +134,7 @@
     public boolean equals(Object other) {
         if (other != null && other instanceof StatusHints) {
             StatusHints otherHints = (StatusHints) other;
-            return Objects.equals(otherHints.getComponentName(), getComponentName()) &&
+            return Objects.equals(otherHints.getPackageName(), getPackageName()) &&
                     Objects.equals(otherHints.getLabel(), getLabel()) &&
                     otherHints.getIconResId() == getIconResId() &&
                     Objects.equals(otherHints.getExtras(), getExtras());
@@ -143,7 +144,7 @@
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(mComponentName) + Objects.hashCode(mLabel) + mIconResId +
+        return Objects.hashCode(mPackageName) + Objects.hashCode(mLabel) + mIconResId +
                 Objects.hashCode(mExtras);
     }
 }
diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java
index b8f6964..5e9e6d0 100644
--- a/telecomm/java/android/telecomm/TelecommManager.java
+++ b/telecomm/java/android/telecomm/TelecommManager.java
@@ -46,34 +46,34 @@
      *
      * @hide
      */
-    public static final String ACTION_INCOMING_CALL = "android.intent.action.INCOMING_CALL";
+    public static final String ACTION_INCOMING_CALL = "android.telecomm.action.INCOMING_CALL";
 
     /**
      * The {@link android.content.Intent} action used to configure a
      * {@link android.telecomm.ConnectionService}.
      */
     public static final String ACTION_CONNECTION_SERVICE_CONFIGURE =
-            "android.intent.action.CONNECTION_SERVICE_CONFIGURE";
+            "android.telecomm.action.CONNECTION_SERVICE_CONFIGURE";
 
     /**
      * The {@link android.content.Intent} action used to show the call settings page.
      */
     public static final String ACTION_SHOW_CALL_SETTINGS =
-            "android.telecomm.intent.action.SHOW_CALL_SETTINGS";
+            "android.telecomm.action.SHOW_CALL_SETTINGS";
 
     /**
      * The {@link android.content.Intent} action used to show the settings page used to configure
      * {@link PhoneAccount} preferences.
      */
     public static final String ACTION_CHANGE_PHONE_ACCOUNTS =
-            "android.telecomm.intent.action.CHANGE_PHONE_ACCOUNTS";
+            "android.telecomm.action.CHANGE_PHONE_ACCOUNTS";
 
     /**
      * Optional extra for {@link android.content.Intent#ACTION_CALL} containing a boolean that
      * determines whether the speakerphone should be automatically turned on for an outgoing call.
      */
     public static final String EXTRA_START_CALL_WITH_SPEAKERPHONE =
-            "android.intent.extra.START_CALL_WITH_SPEAKERPHONE";
+            "android.telecomm.extra.START_CALL_WITH_SPEAKERPHONE";
 
     /**
      * Optional extra for {@link android.content.Intent#ACTION_CALL} containing an integer that
@@ -86,7 +86,7 @@
      * @hide
      */
     public static final String EXTRA_START_CALL_WITH_VIDEO_STATE =
-            "android.intent.extra.START_CALL_WITH_VIDEO_STATE";
+            "android.telecomm.extra.START_CALL_WITH_VIDEO_STATE";
 
     /**
      * The extra used with an {@link android.content.Intent#ACTION_CALL} and
@@ -96,7 +96,7 @@
      * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
      */
     public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
-            "android.intent.extra.PHONE_ACCOUNT_HANDLE";
+            "android.telecomm.extra.PHONE_ACCOUNT_HANDLE";
 
     /**
      * Optional extra for {@link #ACTION_INCOMING_CALL} containing a {@link Bundle} which contains
@@ -106,7 +106,7 @@
      * @hide
      */
     public static final String EXTRA_INCOMING_CALL_EXTRAS =
-            "android.intent.extra.INCOMING_CALL_EXTRAS";
+            "android.telecomm.extra.INCOMING_CALL_EXTRAS";
 
     /**
      * Optional extra for {@link android.content.Intent#ACTION_CALL} and
@@ -117,7 +117,7 @@
      * @hide
      */
     public static final String EXTRA_OUTGOING_CALL_EXTRAS =
-            "android.intent.extra.OUTGOING_CALL_EXTRAS";
+            "android.telecomm.extra.OUTGOING_CALL_EXTRAS";
 
     /**
      * Optional extra for {@link android.telephony.TelephonyManager#ACTION_PHONE_STATE_CHANGED}
@@ -203,7 +203,7 @@
      * @hide
      */
     public static final String ACTION_CURRENT_TTY_MODE_CHANGED =
-            "android.telecomm.intent.action.CURRENT_TTY_MODE_CHANGED";
+            "android.telecomm.action.CURRENT_TTY_MODE_CHANGED";
 
     /**
      * The lookup key for an int that indicates the current TTY mode.
@@ -226,7 +226,7 @@
      * @hide
      */
     public static final String ACTION_TTY_PREFERRED_MODE_CHANGED =
-            "android.telecomm.intent.action.TTY_PREFERRED_MODE_CHANGED";
+            "android.telecomm.action.TTY_PREFERRED_MODE_CHANGED";
 
     /**
      * The lookup key for an int that indicates preferred TTY mode. Valid modes are: -
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
index 32b877d..a673733 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
@@ -65,6 +65,10 @@
 
     void splitFromConference(String callId);
 
+    void mergeConference(String conferenceCallId);
+
+    void swapConference(String conferenceCallId);
+
     void onPostDialContinue(String callId, boolean proceed);
 
     void onPhoneAccountClicked(String callId);
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
index 2ce5c6b..626bb91 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
@@ -54,6 +54,10 @@
 
     void splitFromConference(String callId);
 
+    void mergeConference(String callId);
+
+    void swapConference(String callId);
+
     void turnOnProximitySensor();
 
     void turnOffProximitySensor(boolean screenOnImmediately);
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 8af5e98..1d9e6a9 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -38,8 +38,8 @@
 
 import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_IDP_STRING;
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING;
 
 import java.util.Locale;
 import java.util.regex.Matcher;
@@ -2215,81 +2215,79 @@
     cdmaCheckAndProcessPlusCodeByNumberFormat(String dialStr,int currFormat,int defaultFormat) {
         String retStr = dialStr;
 
+        boolean useNanp = (currFormat == defaultFormat) && (currFormat == FORMAT_NANP);
+
         // Checks if the plus sign character is in the passed-in dial string
         if (dialStr != null &&
             dialStr.lastIndexOf(PLUS_SIGN_STRING) != -1) {
-            // Format the string based on the rules for the country the number is from,
-            // and the current country the phone is camped on.
-            if ((currFormat == defaultFormat) && (currFormat == FORMAT_NANP)) {
-                // Handle case where default and current telephone numbering plans are NANP.
-                String postDialStr = null;
-                String tempDialStr = dialStr;
 
-                // Sets the retStr to null since the conversion will be performed below.
-                retStr = null;
-                if (DBG) log("checkAndProcessPlusCode,dialStr=" + dialStr);
-                // This routine is to process the plus sign in the dial string by loop through
-                // the network portion, post dial portion 1, post dial portion 2... etc. if
-                // applied
-                do {
-                    String networkDialStr;
+            // Handle case where default and current telephone numbering plans are NANP.
+            String postDialStr = null;
+            String tempDialStr = dialStr;
+
+            // Sets the retStr to null since the conversion will be performed below.
+            retStr = null;
+            if (DBG) log("checkAndProcessPlusCode,dialStr=" + dialStr);
+            // This routine is to process the plus sign in the dial string by loop through
+            // the network portion, post dial portion 1, post dial portion 2... etc. if
+            // applied
+            do {
+                String networkDialStr;
+                // Format the string based on the rules for the country the number is from,
+                // and the current country the phone is camped
+                if (useNanp) {
                     networkDialStr = extractNetworkPortion(tempDialStr);
-                    // Handles the conversion within NANP
-                    networkDialStr = processPlusCodeWithinNanp(networkDialStr);
+                } else  {
+                    networkDialStr = extractNetworkPortionAlt(tempDialStr);
 
-                    // Concatenates the string that is converted from network portion
-                    if (!TextUtils.isEmpty(networkDialStr)) {
-                        if (retStr == null) {
-                            retStr = networkDialStr;
-                        } else {
-                            retStr = retStr.concat(networkDialStr);
-                        }
+                }
+
+                networkDialStr = processPlusCode(networkDialStr, useNanp);
+
+                // Concatenates the string that is converted from network portion
+                if (!TextUtils.isEmpty(networkDialStr)) {
+                    if (retStr == null) {
+                        retStr = networkDialStr;
                     } else {
-                        // This should never happen since we checked the if dialStr is null
-                        // and if it contains the plus sign in the beginning of this function.
-                        // The plus sign is part of the network portion.
-                        Rlog.e("checkAndProcessPlusCode: null newDialStr", networkDialStr);
-                        return dialStr;
+                        retStr = retStr.concat(networkDialStr);
                     }
-                    postDialStr = extractPostDialPortion(tempDialStr);
-                    if (!TextUtils.isEmpty(postDialStr)) {
-                        int dialableIndex = findDialableIndexFromPostDialStr(postDialStr);
+                } else {
+                    // This should never happen since we checked the if dialStr is null
+                    // and if it contains the plus sign in the beginning of this function.
+                    // The plus sign is part of the network portion.
+                    Rlog.e("checkAndProcessPlusCode: null newDialStr", networkDialStr);
+                    return dialStr;
+                }
+                postDialStr = extractPostDialPortion(tempDialStr);
+                if (!TextUtils.isEmpty(postDialStr)) {
+                    int dialableIndex = findDialableIndexFromPostDialStr(postDialStr);
 
-                        // dialableIndex should always be greater than 0
-                        if (dialableIndex >= 1) {
-                            retStr = appendPwCharBackToOrigDialStr(dialableIndex,
-                                     retStr,postDialStr);
-                            // Skips the P/W character, extracts the dialable portion
-                            tempDialStr = postDialStr.substring(dialableIndex);
-                        } else {
-                            // Non-dialable character such as P/W should not be at the end of
-                            // the dial string after P/W processing in CdmaConnection.java
-                            // Set the postDialStr to "" to break out of the loop
-                            if (dialableIndex < 0) {
-                                postDialStr = "";
-                            }
-                            Rlog.e("wrong postDialStr=", postDialStr);
+                    // dialableIndex should always be greater than 0
+                    if (dialableIndex >= 1) {
+                        retStr = appendPwCharBackToOrigDialStr(dialableIndex,
+                                 retStr,postDialStr);
+                        // Skips the P/W character, extracts the dialable portion
+                        tempDialStr = postDialStr.substring(dialableIndex);
+                    } else {
+                        // Non-dialable character such as P/W should not be at the end of
+                        // the dial string after P/W processing in CdmaConnection.java
+                        // Set the postDialStr to "" to break out of the loop
+                        if (dialableIndex < 0) {
+                            postDialStr = "";
                         }
+                        Rlog.e("wrong postDialStr=", postDialStr);
                     }
-                    if (DBG) log("checkAndProcessPlusCode,postDialStr=" + postDialStr);
-                } while (!TextUtils.isEmpty(postDialStr) && !TextUtils.isEmpty(tempDialStr));
-            } else {
-                // TODO: Support NANP international conversion and other telephone numbering plans.
-                // Currently the phone is never used in non-NANP system, so return the original
-                // dial string.
-                Rlog.e("checkAndProcessPlusCode:non-NANP not supported", dialStr);
-            }
+                }
+                if (DBG) log("checkAndProcessPlusCode,postDialStr=" + postDialStr);
+            } while (!TextUtils.isEmpty(postDialStr) && !TextUtils.isEmpty(tempDialStr));
         }
         return retStr;
-     }
+    }
 
-    // This function gets the default international dialing prefix
-    private static String getDefaultIdp( ) {
-        String ps = null;
-        SystemProperties.get(PROPERTY_IDP_STRING, ps);
-        if (TextUtils.isEmpty(ps)) {
-            ps = NANP_IDP_STRING;
-        }
+    private static String getCurrentIdp(boolean useNanp) {
+        // in case, there is no IDD is found, we shouldn't convert it.
+        String ps = SystemProperties.get(
+                PROPERTY_OPERATOR_IDP_STRING, useNanp ? NANP_IDP_STRING : PLUS_SIGN_STRING);
         return ps;
     }
 
@@ -2399,31 +2397,32 @@
     }
 
     /**
-     * This function handles the plus code conversion within NANP CDMA network
+     * This function handles the plus code conversion
      * If the number format is
      * 1)+1NANP,remove +,
      * 2)other than +1NANP, any + numbers,replace + with the current IDP
      */
-    private static String processPlusCodeWithinNanp(String networkDialStr) {
+    private static String processPlusCode(String networkDialStr, boolean useNanp) {
         String retStr = networkDialStr;
 
-        if (DBG) log("processPlusCodeWithinNanp,networkDialStr=" + networkDialStr);
+        if (DBG) log("processPlusCode, networkDialStr = " + networkDialStr
+                + "for NANP = " + useNanp);
         // If there is a plus sign at the beginning of the dial string,
         // Convert the plus sign to the default IDP since it's an international number
         if (networkDialStr != null &&
             networkDialStr.charAt(0) == PLUS_SIGN_CHAR &&
             networkDialStr.length() > 1) {
             String newStr = networkDialStr.substring(1);
-            if (isOneNanp(newStr)) {
+            // TODO: for nonNanp, should the '+' be removed if following number is country code
+            if (useNanp && isOneNanp(newStr)) {
                 // Remove the leading plus sign
                 retStr = newStr;
-             } else {
-                 String idpStr = getDefaultIdp();
-                 // Replaces the plus sign with the default IDP
-                 retStr = networkDialStr.replaceFirst("[+]", idpStr);
+            } else {
+                // Replaces the plus sign with the default IDP
+                retStr = networkDialStr.replaceFirst("[+]", getCurrentIdp(useNanp));
             }
         }
-        if (DBG) log("processPlusCodeWithinNanp,retStr=" + retStr);
+        if (DBG) log("processPlusCode, retStr=" + retStr);
         return retStr;
     }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index cdee3de..93c49ba 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2511,9 +2511,9 @@
      * @param content String containing SAT/USAT response in hexadecimal
      *                format starting with command tag. See TS 102 223 for
      *                details.
-     * @return The APDU response from the ICC card, with the last 4 bytes
-     *         being the status word. If the command fails, returns an empty
-     *         string.
+     * @return The APDU response from the ICC card in hexadecimal format
+     *         with the last 4 bytes being the status word. If the command fails,
+     *         returns an empty string.
      */
     public String sendEnvelopeWithStatus(String content) {
         try {
@@ -2903,27 +2903,6 @@
     }
 
     /**
-     * Get the calculated preferred network type.
-     * Used for debugging incorrect network type.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     *
-     * @return the preferred network type, defined in RILConstants.java or -1 if
-     *         none available.
-     */
-    public int getCalculatedPreferredNetworkType() {
-        try {
-            return getITelephony().getCalculatedPreferredNetworkType();
-        } catch (RemoteException ex) {
-            Rlog.e(TAG, "getCalculatedPreferredNetworkType RemoteException", ex);
-        } catch (NullPointerException ex) {
-            Rlog.e(TAG, "getCalculatedPreferredNetworkType NPE", ex);
-        }
-        return -1;
-    }
-
-    /**
      * Get the preferred network type.
      * Used for device configuration by some CDMA operators.
      * <p>
@@ -2932,6 +2911,7 @@
      * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
      *
      * @return the preferred network type, defined in RILConstants.java.
+     * @hide
      */
     public int getPreferredNetworkType() {
         try {
@@ -2954,6 +2934,7 @@
      *
      * @param networkType the preferred network type, defined in RILConstants.java.
      * @return true on success; false on any failure.
+     * @hide
      */
     public boolean setPreferredNetworkType(int networkType) {
         try {
@@ -2967,25 +2948,17 @@
     }
 
     /**
-     * Set the CDMA subscription source.
-     * Used for device supporting both NV and RUIM for CDMA.
+     * Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA.
+     *
      * <p>
      * Requires Permission:
      *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
      *
-     * @param subscriptionType the subscription type, 0 for RUIM, 1 for NV.
      * @return true on success; false on any failure.
      */
-    public boolean setCdmaSubscription(int subscriptionType) {
-        try {
-            return getITelephony().setCdmaSubscription(subscriptionType);
-        } catch (RemoteException ex) {
-            Rlog.e(TAG, "setCdmaSubscription RemoteException", ex);
-        } catch (NullPointerException ex) {
-            Rlog.e(TAG, "setCdmaSubscription NPE", ex);
-        }
-        return false;
+    public boolean setGlobalPreferredNetworkType() {
+        return setPreferredNetworkType(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
     }
 
     /**
@@ -3023,9 +2996,9 @@
     }
 
     /**
-     * Override the branding for the input ICCID.
+     * Override the branding for the current ICCID.
      *
-     * Once set, whenever the ICCID is inserted into the device, the service
+     * Once set, whenever the SIM is present in the device, the service
      * provider name (SPN) and the operator name will both be replaced by the
      * brand value input. To unset the value, the same function should be
      * called with a null brand value.
@@ -3034,14 +3007,12 @@
      *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      *  or has to be carrier app - see #hasCarrierPrivileges.
      *
-     * @param iccId The ICCID of that the branding applies to.
      * @param brand The brand name to display/set.
      * @return true if the operation was executed correctly.
      */
-    public boolean setOperatorBrandOverride(String iccId, String brand) {
-        // TODO: Validate ICCID format.
+    public boolean setOperatorBrandOverride(String brand) {
         try {
-            return getITelephony().setOperatorBrandOverride(iccId, brand);
+            return getITelephony().setOperatorBrandOverride(brand);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "setOperatorBrandOverride RemoteException", ex);
         } catch (NullPointerException ex) {
@@ -3393,6 +3364,7 @@
      * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
      *
      * @param enable true means enabling the simplified UI.
+     * @hide
      */
     public void enableSimplifiedNetworkSettings(boolean enable) {
         enableSimplifiedNetworkSettings(getDefaultSubscription(), enable);
@@ -3408,6 +3380,7 @@
      *
      * @param subId for which the simplified UI should be enabled or disabled.
      * @param enable true means enabling the simplified UI.
+     * @hide
      */
     public void enableSimplifiedNetworkSettings(long subId, boolean enable) {
         try {
@@ -3424,6 +3397,7 @@
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      *
      * @return true if the simplified UI is enabled.
+     * @hide
      */
     public boolean getSimplifiedNetworkSettingsEnabled() {
         return getSimplifiedNetworkSettingsEnabled(getDefaultSubscription());
@@ -3437,6 +3411,7 @@
      *
      * @param subId for which the simplified UI should be enabled or disabled.
      * @return true if the simplified UI is enabled.
+     * @hide
      */
     public boolean getSimplifiedNetworkSettingsEnabled(long subId) {
         try {
diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
index 4cba70d..d1c8ef0 100644
--- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java
+++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
@@ -609,16 +609,25 @@
                 }
             } else {
                 if (prevWasEscape) {
-                    char shiftChar = shiftTableToChar.charAt(c);
+                    char shiftChar =
+                            c < shiftTableToChar.length() ? shiftTableToChar.charAt(c) : ' ';
                     if (shiftChar == ' ') {
                         // display character from main table if not present in shift table
-                        ret.append(languageTableToChar.charAt(c));
+                        if (c < languageTableToChar.length()) {
+                            ret.append(languageTableToChar.charAt(c));
+                        } else {
+                            ret.append(' ');
+                        }
                     } else {
                         ret.append(shiftChar);
                     }
                 } else {
                     if (!isMbcs || c < 0x80 || i + 1 >= offset + length) {
-                        ret.append(languageTableToChar.charAt(c));
+                        if (c < languageTableToChar.length()) {
+                            ret.append(languageTableToChar.charAt(c));
+                        } else {
+                            ret.append(' ');
+                        }
                     } else {
                         // isMbcs must be true. So both mbcsBuffer and charset are initialized.
                         mbcsBuffer.clear();
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 5c3dcdb..79c72b88 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -643,15 +643,6 @@
     boolean setPreferredNetworkType(int networkType);
 
     /**
-     * Set the CDMA subscription source.
-     * Used for device supporting both NV and RUIM for CDMA.
-     *
-     * @param subscriptionType the subscription type, 0 for RUIM, 1 for NV.
-     * @return true on success; false on any failure.
-     */
-    boolean setCdmaSubscription(int subscriptionType);
-
-    /**
      * User enable/disable Mobile Data.
      *
      * @param enable true to turn on, else false
@@ -766,9 +757,9 @@
     String getLine1AlphaTagForDisplay(long subId);
 
     /**
-     * Override the operator branding for the input ICCID.
+     * Override the operator branding for the current ICCID.
      *
-     * Once set, whenever the ICCID is inserted into the device, the service
+     * Once set, whenever the SIM is present in the device, the service
      * provider name (SPN) and the operator name will both be replaced by the
      * brand value input. To unset the value, the same function should be
      * called with a null brand value.
@@ -777,11 +768,10 @@
      *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      *  or has to be carrier app - see #hasCarrierPrivileges.
      *
-     * @param iccid The ICCID of that the branding applies to.
      * @param brand The brand name to display/set.
      * @return true if the operation was executed correctly.
      */
-    boolean setOperatorBrandOverride(String iccId, String brand);
+    boolean setOperatorBrandOverride(String brand);
 
     /**
      * Returns the result and response from RIL for oem request
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 5ec4247..34992b8 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -123,8 +123,8 @@
     /** Indicate the timer value for exiting emergency callback mode */
     static final String PROPERTY_ECM_EXIT_TIMER = "ro.cdma.ecmexittimer";
 
-    /** The international dialing prefix conversion string */
-    static final String PROPERTY_IDP_STRING = "ro.cdma.idpstring";
+    /** the international dialing prefix of current operator network */
+    static final String PROPERTY_OPERATOR_IDP_STRING = "telephony.operator.idpstring";
 
     /**
      * Defines the schema for the carrier specified OTASP number
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index e03b9c8..44787e7 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -30,7 +30,6 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.graphics.BitmapFactory;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -391,6 +390,17 @@
     }
 
     @Override
+    protected void onPause() {
+        super.onPause();
+        Log.i(TAG, "I'm such a slooow poor loser");
+        try {
+            Thread.sleep(500);
+        } catch (InterruptedException e) {
+        }
+        Log.i(TAG, "See?");
+    }
+
+    @Override
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
         if (mOverrideConfig != null) {
diff --git a/tests/Camera2Tests/CameraToo/src/com/example/android/camera2/cameratoo/CameraTooActivity.java b/tests/Camera2Tests/CameraToo/src/com/example/android/camera2/cameratoo/CameraTooActivity.java
index c630bad..d513f44 100644
--- a/tests/Camera2Tests/CameraToo/src/com/example/android/camera2/cameratoo/CameraTooActivity.java
+++ b/tests/Camera2Tests/CameraToo/src/com/example/android/camera2/cameratoo/CameraTooActivity.java
@@ -290,14 +290,14 @@
 
                 // Open the camera device
                 try {
-                    mCameraManager.openCamera(mCameraId, mCameraStateListener,
+                    mCameraManager.openCamera(mCameraId, mCameraStateCallback,
                             mBackgroundHandler);
                 } catch (CameraAccessException ex) {
                     Log.e(TAG, "Failed to configure output surface", ex);
                 }
                 mGotSecondCallback = true;
 
-                // Control flow continues in mCameraStateListener.onOpened()
+                // Control flow continues in mCameraStateCallback.onOpened()
             }
         }};
 
@@ -305,8 +305,8 @@
      * Calledbacks invoked upon state changes in our {@code CameraDevice}. <p>These are run on
      * {@code mBackgroundThread}.</p>
      */
-    final CameraDevice.StateListener mCameraStateListener =
-            new CameraDevice.StateListener() {
+    final CameraDevice.StateCallback mCameraStateCallback =
+            new CameraDevice.StateCallback() {
         @Override
         public void onOpened(CameraDevice camera) {
             Log.i(TAG, "Successfully opened camera");
@@ -337,8 +337,8 @@
      * Callbacks invoked upon state changes in our {@code CameraCaptureSession}. <p>These are run on
      * {@code mBackgroundThread}.</p>
      */
-    final CameraCaptureSession.StateListener mCaptureSessionListener =
-            new CameraCaptureSession.StateListener() {
+    final CameraCaptureSession.StateCallback mCaptureSessionListener =
+            new CameraCaptureSession.StateCallback() {
         @Override
         public void onConfigured(CameraCaptureSession session) {
             Log.i(TAG, "Finished configuring camera outputs");
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/samples/simplecamera/Camera2Source.java b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/samples/simplecamera/Camera2Source.java
index 05057f2..07dfb54 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/samples/simplecamera/Camera2Source.java
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/samples/simplecamera/Camera2Source.java
@@ -38,7 +38,7 @@
 import android.view.Surface;
 import com.android.ex.camera2.blocking.BlockingCameraManager;
 import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
-import com.android.ex.camera2.blocking.BlockingSessionListener;
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
 import androidx.media.filterfw.Filter;
 import androidx.media.filterfw.Frame;
 import androidx.media.filterfw.FrameImage2D;
@@ -72,7 +72,7 @@
 
     private static final long SESSION_TIMEOUT_MS = 2000;
 
-    class MyCameraListener extends CameraManager.AvailabilityListener {
+    class MyCameraListener extends CameraManager.AvailabilityCallback {
 
         @Override
         public void onCameraAvailable(String cameraId) {
@@ -88,7 +88,7 @@
 
     }
 
-    class MyCaptureListener extends CameraCaptureSession.CaptureListener {
+    class MyCaptureCallback extends CameraCaptureSession.CaptureCallback {
 
         @Override
         public void onCaptureCompleted(CameraCaptureSession camera, CaptureRequest request,
@@ -189,7 +189,7 @@
         surfaces.add(mSurface);
         CaptureRequest.Builder mCaptureRequest = null;
         try {
-            BlockingSessionListener blkSession = new BlockingSessionListener();
+            BlockingSessionCallback blkSession = new BlockingSessionCallback();
 
             mCamera.createCaptureSession(surfaces, blkSession, mHandler);
             mCaptureRequest = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
@@ -203,7 +203,7 @@
         }
 
         try {
-            mCameraSession.setRepeatingRequest(mCaptureRequest.build(), new MyCaptureListener(),
+            mCameraSession.setRepeatingRequest(mCaptureRequest.build(), new MyCaptureCallback(),
                     mHandler);
         } catch (CameraAccessException e) {
             e.printStackTrace();
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RevealActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/RevealActivity.java
index 3360e30..256a1d4 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/RevealActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/RevealActivity.java
@@ -17,6 +17,7 @@
 package com.android.test.hwui;
 
 import android.animation.Animator;
+import android.animation.AnimatorSet;
 import android.app.Activity;
 import android.content.Context;
 import android.graphics.Canvas;
@@ -34,6 +35,7 @@
     private static final int DURATION = 800;
 
     private boolean mShouldBlock;
+    private int mIteration = 0;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -57,10 +59,17 @@
         Animator animator = ViewAnimationUtils.createCircularReveal(view,
                 view.getWidth() / 2, view.getHeight() / 2,
                 0, Math.max(view.getWidth(), view.getHeight()));
-        animator.setDuration(DURATION);
-        animator.setAllowRunningAsynchronously(true);
-        animator.start();
+        if (mIteration < 2) {
+            animator.setDuration(DURATION);
+            animator.start();
+        } else {
+            AnimatorSet set = new AnimatorSet();
+            set.playTogether(animator);
+            set.setDuration(DURATION);
+            set.start();
+        }
 
+        mIteration = (mIteration + 1) % 4;
         mShouldBlock = !mShouldBlock;
         if (mShouldBlock) {
             view.post(sBlockThread);
diff --git a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
index 50633db..4e18ce9 100644
--- a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
+++ b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
@@ -94,7 +94,7 @@
 
             // Load the data
             final PackageManager pm = context.getPackageManager();
-            final Intent intent = new Intent(MediaBrowserService.SERVICE_ACTION);
+            final Intent intent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
             final List<ResolveInfo> list = pm.queryIntentServices(intent, 0);
             final int N = list.size();
             mItems = new ArrayList(N);
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
index a216a32..4e2e47e 100644
--- a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
@@ -134,8 +134,8 @@
                         bob.setSubtitle("Summary " + i);
                         bob.setMediaId(Uri.withAppendedPath(BASE_URI,
                                 Integer.toString(i)).toString());
-                        list.add(new MediaBrowser.MediaItem(MediaBrowser.MediaItem.FLAG_BROWSABLE,
-                                bob.build()));
+                        list.add(new MediaBrowser.MediaItem(bob.build(),
+                                MediaBrowser.MediaItem.FLAG_BROWSABLE));
                     }
 
                     result.sendResult(list);
diff --git a/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java b/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java
index d1172ac..ceb0937 100644
--- a/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java
+++ b/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java
@@ -76,7 +76,7 @@
      * destroyed before {@link #onStop} is called.
      */
     public void onStart() {
-        mController.addCallback(mCb);
+        mController.registerCallback(mCb);
         IntentFilter filter = new IntentFilter();
         filter.addAction(RequestUtils.ACTION_FFWD);
         filter.addAction(RequestUtils.ACTION_NEXT);
@@ -100,7 +100,7 @@
      */
     public void onStop() {
         mStarted = false;
-        mController.removeCallback(mCb);
+        mController.unregisterCallback(mCb);
         mService.unregisterReceiver(this);
         updateNotification();
     }
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerController.java b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
index c8d72ca..7861bcc 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerController.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
@@ -159,7 +159,7 @@
         @Override
         public void onServiceDisconnected(ComponentName name) {
             if (mController != null) {
-                mController.removeCallback(mControllerCb);
+                mController.unregisterCallback(mControllerCb);
             }
             mBinder = null;
             mController = null;
@@ -185,7 +185,7 @@
             }
             mController = new MediaController(mContext, token);
             mContext.setMediaController(mController);
-            mController.addCallback(mControllerCb, mHandler);
+            mController.registerCallback(mControllerCb, mHandler);
             mTransportControls = mController.getTransportControls();
             if (mArt != null) {
                 setArt(mArt);
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 2604e97..c403ce6 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -222,7 +222,8 @@
 
     @Override
     public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
-            int startY, IRemoteCallback startedCallback, boolean scaleUp) {
+            int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
+            boolean scaleUp) {
         // TODO Auto-generated method stub
     }