Merge "Manually merge QC's change for SUPL_ES." into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 993ada1..0efa148 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
@@ -8411,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
@@ -8615,21 +8617,16 @@
 
   public class LauncherApps {
     method public void addCallback(android.content.pm.LauncherApps.Callback);
-    method public void addCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
-    method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
-    method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback, android.os.Handler);
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
-    method public boolean isActivityEnabledForProfile(android.content.ComponentName, android.os.UserHandle);
     method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
-    method public boolean isPackageEnabledForProfile(java.lang.String, android.os.UserHandle);
+    method public void registerCallback(android.content.pm.LauncherApps.Callback);
+    method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
     method public void removeCallback(android.content.pm.LauncherApps.Callback);
-    method public void removeOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
     method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
-    method public void showAppDetailsForProfile(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
-    method public void startActivityForProfile(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
+    method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
   }
 
   public static abstract class LauncherApps.Callback {
@@ -8641,10 +8638,6 @@
     method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
   }
 
-  public static abstract class LauncherApps.OnAppsChangedCallback extends android.content.pm.LauncherApps.Callback {
-    ctor public LauncherApps.OnAppsChangedCallback();
-  }
-
   public class PackageInfo implements android.os.Parcelable {
     ctor public PackageInfo();
     method public int describeContents();
@@ -23702,7 +23695,6 @@
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
     field public static final java.lang.String FEATURES = "features";
-    field public static final int FEATURES_NONE = 0; // 0x0
     field public static final int FEATURES_VIDEO = 1; // 0x1
     field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
     field public static final int INCOMING_TYPE = 1; // 0x1
@@ -27426,11 +27418,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();
@@ -27444,7 +27437,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>);
@@ -27457,10 +27450,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
@@ -27533,15 +27526,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);
   }
@@ -27562,7 +27555,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
@@ -28219,7 +28212,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
@@ -28236,7 +28228,7 @@
     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();
@@ -28311,12 +28303,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;
   }
@@ -28347,16 +28338,16 @@
   }
 
   public class PhoneAccount implements android.os.Parcelable {
-    method public static android.telecomm.PhoneAccount.Builder builder();
+    method public static android.telecomm.PhoneAccount.Builder builder(android.telecomm.PhoneAccountHandle, java.lang.CharSequence);
     method public int describeContents();
     method public android.telecomm.PhoneAccountHandle getAccountHandle();
+    method public android.net.Uri getAddress();
     method public int getCapabilities();
-    method public android.net.Uri getHandle();
     method public android.graphics.drawable.Drawable getIcon(android.content.Context);
     method public int getIconResId();
     method public java.lang.CharSequence getLabel();
     method public java.lang.CharSequence getShortDescription();
-    method public java.lang.String getSubscriptionNumber();
+    method public android.net.Uri getSubscriptionAddress();
     method public java.util.List<java.lang.String> getSupportedUriSchemes();
     method public boolean supportsUriScheme(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
@@ -28369,17 +28360,14 @@
   }
 
   public static class PhoneAccount.Builder {
-    ctor public PhoneAccount.Builder();
+    ctor public PhoneAccount.Builder(android.telecomm.PhoneAccountHandle, java.lang.CharSequence);
     method public android.telecomm.PhoneAccount build();
-    method public android.telecomm.PhoneAccount.Builder withAccountHandle(android.telecomm.PhoneAccountHandle);
-    method public android.telecomm.PhoneAccount.Builder withCapabilities(int);
-    method public android.telecomm.PhoneAccount.Builder withHandle(android.net.Uri);
-    method public android.telecomm.PhoneAccount.Builder withIconResId(int);
-    method public android.telecomm.PhoneAccount.Builder withLabel(java.lang.CharSequence);
-    method public android.telecomm.PhoneAccount.Builder withShortDescription(java.lang.CharSequence);
-    method public android.telecomm.PhoneAccount.Builder withSubscriptionNumber(java.lang.String);
-    method public android.telecomm.PhoneAccount.Builder withSupportedUriScheme(java.lang.String);
-    method public android.telecomm.PhoneAccount.Builder withSupportedUriSchemes(java.util.List<java.lang.String>);
+    method public android.telecomm.PhoneAccount.Builder setAddress(android.net.Uri);
+    method public android.telecomm.PhoneAccount.Builder setCapabilities(int);
+    method public android.telecomm.PhoneAccount.Builder setIconResId(int);
+    method public android.telecomm.PhoneAccount.Builder setShortDescription(java.lang.CharSequence);
+    method public android.telecomm.PhoneAccount.Builder setSubscriptionAddress(android.net.Uri);
+    method public android.telecomm.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>);
   }
 
   public class PhoneAccountHandle implements android.os.Parcelable {
@@ -28494,11 +28482,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;
   }
@@ -28892,8 +28880,6 @@
     method public void downloadMultimediaMessage(java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
     method public android.os.Bundle getCarrierConfigValues();
     method public static android.telephony.SmsManager getDefault();
-    method public static android.telephony.SmsManager getSmsManagerUsingSubId(long);
-    method public long getSubId();
     method public void injectSmsPdu(byte[], java.lang.String, android.app.PendingIntent);
     method public void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
     method public void sendMultimediaMessage(android.net.Uri, java.lang.String, android.os.Bundle, android.app.PendingIntent);
@@ -35897,8 +35883,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();
@@ -35913,11 +35899,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);
@@ -37560,6 +37547,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();
@@ -37567,6 +37555,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 a272cf4..3c16276 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -1,11 +1,3 @@
-package android {
-
-  public static final class R.attr {
-    field public static final int __removed1 = 16843955; // 0x10104b3
-  }
-
-}
-
 package android.media {
 
   public class AudioFormat {
@@ -53,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
@@ -63,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);
   }
 
@@ -78,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/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 5f7a17d..27a03b6 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -54,6 +54,10 @@
         int action, in Bundle arguments, int interactionId,
         IAccessibilityInteractionConnectionCallback callback, long threadId);
 
+    boolean computeClickPointInScreen(int accessibilityWindowId, long accessibilityNodeId,
+        int interactionId, IAccessibilityInteractionConnectionCallback callback,
+        long threadId);
+
     AccessibilityWindowInfo getWindow(int windowId);
 
     List<AccessibilityWindowInfo> getWindows();
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/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/Notification.java b/core/java/android/app/Notification.java
index 1083943..c831c25 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3386,8 +3386,16 @@
      */
     public static abstract class Style {
         private CharSequence mBigContentTitle;
-        private CharSequence mSummaryText = null;
-        private boolean mSummaryTextSet = false;
+
+        /**
+         * @hide
+         */
+        protected CharSequence mSummaryText = null;
+
+        /**
+         * @hide
+         */
+        protected boolean mSummaryTextSet = false;
 
         protected Builder mBuilder;
 
@@ -3679,6 +3687,11 @@
      * @see Notification#bigContentView
      */
     public static class BigTextStyle extends Style {
+
+        private static final int MAX_LINES = 13;
+        private static final int LINES_CONSUMED_BY_ACTIONS = 3;
+        private static final int LINES_CONSUMED_BY_SUMMARY = 2;
+
         private CharSequence mBigText;
 
         public BigTextStyle() {
@@ -3745,6 +3758,7 @@
 
             contentView.setTextViewText(R.id.big_text, mBuilder.processLegacyText(mBigText));
             contentView.setViewVisibility(R.id.big_text, View.VISIBLE);
+            contentView.setInt(R.id.big_text, "setMaxLines", calculateMaxLines());
             contentView.setViewVisibility(R.id.text2, View.GONE);
 
             applyTopPadding(contentView);
@@ -3756,6 +3770,24 @@
             return contentView;
         }
 
+        private int calculateMaxLines() {
+            int lineCount = MAX_LINES;
+            boolean hasActions = mBuilder.mActions.size() > 0;
+            boolean hasSummary = (mSummaryTextSet ? mSummaryText : mBuilder.mSubText) != null;
+            if (hasActions) {
+                lineCount -= LINES_CONSUMED_BY_ACTIONS;
+            }
+            if (hasSummary) {
+                lineCount -= LINES_CONSUMED_BY_SUMMARY;
+            }
+
+            // If we have less top padding at the top, we can fit less lines.
+            if (!mBuilder.mHasThreeLines) {
+                lineCount--;
+            }
+            return lineCount;
+        }
+
         /**
          * @hide
          */
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/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/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index f9370b3..d49bc50 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -278,21 +278,21 @@
 
 
     /**
-     * Adds a callback for changes to packages in current and managed profiles.
+     * Registers a callback for changes to packages in current and managed profiles.
      *
-     * @param callback The callback to add.
+     * @param callback The callback to register.
      */
-    public void addCallback(Callback callback) {
-        addCallback(callback, null);
+    public void registerCallback(Callback callback) {
+        registerCallback(callback, null);
     }
 
     /**
-     * Adds a callback for changes to packages in current and managed profiles.
+     * Registers a callback for changes to packages in current and managed profiles.
      *
-     * @param callback The callback to add.
+     * @param callback The callback to register.
      * @param handler that should be used to post callbacks on, may be null.
      */
-    public void addCallback(Callback callback, Handler handler) {
+    public void registerCallback(Callback callback, Handler handler) {
         synchronized (this) {
             if (callback != null && !mCallbacks.contains(callback)) {
                 boolean addedFirstCallback = mCallbacks.size() == 0;
@@ -308,12 +308,12 @@
     }
 
     /**
-     * Removes a callback that was previously added.
+     * Unregisters a callback that was previously registered.
      *
-     * @param callback The callback to remove.
-     * @see #addCallback(Callback)
+     * @param callback The callback to unregister.
+     * @see #registerCallback(Callback)
      */
-    public void removeCallback(Callback callback) {
+    public void unregisterCallback(Callback callback) {
         synchronized (this) {
             removeCallbackLocked(callback);
             if (mCallbacks.size() == 0) {
@@ -500,44 +500,12 @@
         }
     }
 
-    /** Remove after unbundled apps have migrated STOP SHIP */
-    public static abstract class OnAppsChangedCallback extends Callback {
+    /** STOPSHIP remove when launcher 3 has been updated */
+    public void addCallback(Callback callback) {
+        registerCallback(callback);
     }
-
-    /** Remove after unbundled apps have migrated STOP SHIP */
-    public void addOnAppsChangedCallback(OnAppsChangedCallback callback) {
-        addCallback(callback, null);
-    }
-
-    /** Remove after unbundled apps have migrated STOP SHIP */
-    public void addOnAppsChangedCallback(OnAppsChangedCallback callback, Handler handler) {
-        addCallback(callback, handler);
-    }
-
-    /** Remove after unbundled apps have migrated STOP SHIP */
-    public void removeOnAppsChangedCallback(OnAppsChangedCallback callback) {
-        removeCallback(callback);
-    }
-
-    /** Remove after unbundled apps have migrated STOP SHIP */
-    public void startActivityForProfile(ComponentName component, UserHandle user, Rect sourceBounds,
-            Bundle opts) {
-        startMainActivity(component, user, sourceBounds, opts);
-    }
-
-    /** Remove after unbundled apps have migrated STOP SHIP */
-    public void showAppDetailsForProfile(ComponentName component, UserHandle user,
-            Rect sourceBounds, Bundle opts) {
-        startAppDetailsActivity(component, user, sourceBounds, opts);
-    }
-
-    /** Remove after unbundled apps have migrated STOP SHIP */
-    public boolean isPackageEnabledForProfile(String packageName, UserHandle user) {
-        return isPackageEnabled(packageName, user);
-    }
-
-    /** Remove after unbundled apps have migrated STOP SHIP */
-    public boolean isActivityEnabledForProfile(ComponentName component, UserHandle user) {
-        return isActivityEnabled(component, user);
+    /** STOPSHIP remove when launcher 3 has been updated */
+    public void removeCallback(Callback callback) {
+        unregisterCallback(callback);
     }
 }
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 0a211cf..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,6 +306,11 @@
     /**
      * 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) throws IOException {
         try {
@@ -319,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 {
@@ -331,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 {
@@ -341,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);
@@ -350,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 {
@@ -361,7 +388,7 @@
     }
 
     /**
-     * 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();
@@ -379,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 {
@@ -547,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());
@@ -560,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.
@@ -593,7 +622,7 @@
     }
 
     /**
-     * Unregister an existing callback.
+     * Unregister a previously registered callback.
      */
     public void unregisterSessionCallback(@NonNull SessionCallback callback) {
         synchronized (mDelegates) {
@@ -686,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 {
@@ -719,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 {
@@ -738,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 {
@@ -759,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 {
@@ -783,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 {
@@ -937,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);
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/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/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/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 5fa1cc9..a5e86d8 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -167,8 +167,6 @@
          */
         public static final String FEATURES = "features";
 
-        /** Call had no associated features (e.g. voice-only). */
-        public static final int FEATURES_NONE = 0x0;
         /** Call had video. */
         public static final int FEATURES_VIDEO = 0x1;
 
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/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index a10dda3..a283b91 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -19,7 +19,6 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -101,7 +100,7 @@
             IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
             long interrogatingTid, MagnificationSpec spec) {
         Message message = mHandler.obtainMessage();
-        message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID;
+        message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID;
         message.arg1 = flags;
 
         SomeArgs args = SomeArgs.obtain();
@@ -176,7 +175,7 @@
             IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
             long interrogatingTid, MagnificationSpec spec) {
         Message message = mHandler.obtainMessage();
-        message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID;
+        message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID;
         message.arg1 = flags;
         message.arg2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
 
@@ -261,7 +260,7 @@
             IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
             long interrogatingTid, MagnificationSpec spec) {
         Message message = mHandler.obtainMessage();
-        message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT;
+        message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT;
         message.arg1 = flags;
 
         SomeArgs args = SomeArgs.obtain();
@@ -637,6 +636,95 @@
         }
     }
 
+    public void computeClickPointInScreenClientThread(long accessibilityNodeId,
+            Region interactiveRegion, int interactionId,
+            IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
+            long interrogatingTid, MagnificationSpec spec) {
+        Message message = mHandler.obtainMessage();
+        message.what = PrivateHandler.MSG_COMPUTE_CLICK_POINT_IN_SCREEN;
+
+        SomeArgs args = SomeArgs.obtain();
+        args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
+        args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
+        args.argi3 = interactionId;
+        args.arg1 = callback;
+        args.arg2 = spec;
+        args.arg3 = interactiveRegion;
+
+        message.obj = args;
+
+        // If the interrogation is performed by the same thread as the main UI
+        // thread in this process, set the message as a static reference so
+        // after this call completes the same thread but in the interrogating
+        // client can handle the message to generate the result.
+        if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
+            AccessibilityInteractionClient.getInstanceForThread(
+                    interrogatingTid).setSameThreadMessage(message);
+        } else {
+            mHandler.sendMessage(message);
+        }
+    }
+
+    private void computeClickPointInScreenUiThread(Message message) {
+        SomeArgs args = (SomeArgs) message.obj;
+        final int accessibilityViewId = args.argi1;
+        final int virtualDescendantId = args.argi2;
+        final int interactionId = args.argi3;
+        final IAccessibilityInteractionConnectionCallback callback =
+                (IAccessibilityInteractionConnectionCallback) args.arg1;
+        final MagnificationSpec spec = (MagnificationSpec) args.arg2;
+        final Region interactiveRegion = (Region) args.arg3;
+        args.recycle();
+
+        boolean succeeded = false;
+        Point point = mTempPoint;
+        try {
+            if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
+                return;
+            }
+            View target = null;
+            if (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+                target = findViewByAccessibilityId(accessibilityViewId);
+            } else {
+                target = mViewRootImpl.mView;
+            }
+            if (target != null && isShown(target)) {
+                AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
+                if (provider != null) {
+                    // For virtual views just use the center of the bounds in screen.
+                    AccessibilityNodeInfo node = null;
+                    if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+                        node = provider.createAccessibilityNodeInfo(virtualDescendantId);
+                    } else {
+                        node = provider.createAccessibilityNodeInfo(
+                                AccessibilityNodeProvider.HOST_VIEW_ID);
+                    }
+                    if (node != null) {
+                        succeeded = true;
+                        Rect boundsInScreen = mTempRect;
+                        node.getBoundsInScreen(boundsInScreen);
+                        point.set(boundsInScreen.centerX(), boundsInScreen.centerY());
+                    }
+                } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+                    // For a real view, ask the view to compute the click point.
+                    succeeded = target.computeClickPointInScreenForAccessibility(
+                            interactiveRegion, point);
+                }
+            }
+        } finally {
+            try {
+                Point result = null;
+                if (succeeded) {
+                    applyAppScaleAndMagnificationSpecIfNeeded(point, spec);
+                    result = point;
+                }
+                callback.setComputeClickPointInScreenActionResult(result, interactionId);
+            } catch (RemoteException re) {
+                /* ignore - the other side will time out */
+            }
+        }
+    }
+
     private View findViewByAccessibilityId(int accessibilityId) {
         View root = mViewRootImpl.mView;
         if (root == null) {
@@ -688,6 +776,26 @@
         }
     }
 
+    private void applyAppScaleAndMagnificationSpecIfNeeded(Point point,
+            MagnificationSpec spec) {
+        final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
+        if (!shouldApplyAppScaleAndMagnificationSpec(applicationScale, spec)) {
+            return;
+        }
+
+        if (applicationScale != 1.0f) {
+            point.x *= applicationScale;
+            point.y *= applicationScale;
+        }
+
+        if (spec != null) {
+            point.x *= spec.scale;
+            point.y *= spec.scale;
+            point.x += (int) spec.offsetX;
+            point.y += (int) spec.offsetY;
+        }
+    }
+
     private void applyAppScaleAndMagnificationSpecIfNeeded(AccessibilityNodeInfo info,
             MagnificationSpec spec) {
         if (info == null) {
@@ -1080,11 +1188,12 @@
 
     private class PrivateHandler extends Handler {
         private final static int MSG_PERFORM_ACCESSIBILITY_ACTION = 1;
-        private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID = 2;
-        private final static int MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID = 3;
-        private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT = 4;
+        private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID = 2;
+        private final static int MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID = 3;
+        private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT = 4;
         private final static int MSG_FIND_FOCUS = 5;
         private final static int MSG_FOCUS_SEARCH = 6;
+        private final static int MSG_COMPUTE_CLICK_POINT_IN_SCREEN = 7;
 
         public PrivateHandler(Looper looper) {
             super(looper);
@@ -1096,16 +1205,18 @@
             switch (type) {
                 case MSG_PERFORM_ACCESSIBILITY_ACTION:
                     return "MSG_PERFORM_ACCESSIBILITY_ACTION";
-                case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID:
-                    return "MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID";
-                case MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID:
-                    return "MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID";
-                case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT:
-                    return "MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT";
+                case MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID:
+                    return "MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID";
+                case MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID:
+                    return "MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID";
+                case MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT:
+                    return "MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT";
                 case MSG_FIND_FOCUS:
                     return "MSG_FIND_FOCUS";
                 case MSG_FOCUS_SEARCH:
                     return "MSG_FOCUS_SEARCH";
+                case MSG_COMPUTE_CLICK_POINT_IN_SCREEN:
+                    return "MSG_COMPUTE_CLICK_POINT_IN_SCREEN";
                 default:
                     throw new IllegalArgumentException("Unknown message type: " + type);
             }
@@ -1115,16 +1226,16 @@
         public void handleMessage(Message message) {
             final int type = message.what;
             switch (type) {
-                case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID: {
+                case MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID: {
                     findAccessibilityNodeInfoByAccessibilityIdUiThread(message);
                 } break;
                 case MSG_PERFORM_ACCESSIBILITY_ACTION: {
                     perfromAccessibilityActionUiThread(message);
                 } break;
-                case MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID: {
+                case MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID: {
                     findAccessibilityNodeInfosByViewIdUiThread(message);
                 } break;
-                case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT: {
+                case MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT: {
                     findAccessibilityNodeInfosByTextUiThread(message);
                 } break;
                 case MSG_FIND_FOCUS: {
@@ -1133,6 +1244,9 @@
                 case MSG_FOCUS_SEARCH: {
                     focusSearchUiThread(message);
                 } break;
+                case MSG_COMPUTE_CLICK_POINT_IN_SCREEN: {
+                    computeClickPointInScreenUiThread(message);
+                } break;
                 default:
                     throw new IllegalArgumentException("Unknown message type: " + type);
             }
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/View.java b/core/java/android/view/View.java
index 770e78c..82c5425 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -35,6 +35,8 @@
 import android.graphics.Matrix;
 import android.graphics.Outline;
 import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.PorterDuff;
@@ -5731,6 +5733,136 @@
     }
 
     /**
+     * Computes a point on which a sequence of a down/up event can be sent to
+     * trigger clicking this view. This method is for the exclusive use by the
+     * accessibility layer to determine where to send a click event in explore
+     * by touch mode.
+     *
+     * @param interactiveRegion The interactive portion of this window.
+     * @param outPoint The point to populate.
+     * @return True of such a point exists.
+     */
+    boolean computeClickPointInScreenForAccessibility(Region interactiveRegion,
+            Point outPoint) {
+        // Since the interactive portion of the view is a region but as a view
+        // may have a transformation matrix which cannot be applied to a
+        // region we compute the view bounds rectangle and all interactive
+        // predecessor's and sibling's (siblings of predecessors included)
+        // rectangles that intersect the view bounds. At the
+        // end if the view was partially covered by another interactive
+        // view we compute the view's interactive region and pick a point
+        // on its boundary path as regions do not offer APIs to get inner
+        // points. Note that the the code is optimized to fail early and
+        // avoid unnecessary allocations plus computations.
+
+        // The current approach has edge cases that may produce false
+        // positives or false negatives. For example, a portion of the
+        // view may be covered by an interactive descendant of a
+        // predecessor, which we do not compute. Also a view may be handling
+        // raw touch events instead registering click listeners, which
+        // we cannot compute. Despite these limitations this approach will
+        // work most of the time and it is a huge improvement over just
+        // blindly sending the down and up events in the center of the
+        // view.
+
+        // Cannot click on an unattached view.
+        if (mAttachInfo == null) {
+            return false;
+        }
+
+        // Attached to an invisible window means this view is not visible.
+        if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
+            return false;
+        }
+
+        RectF bounds = mAttachInfo.mTmpTransformRect;
+        bounds.set(0, 0, getWidth(), getHeight());
+        List<RectF> intersections = mAttachInfo.mTmpRectList;
+        intersections.clear();
+
+        if (mParent instanceof ViewGroup) {
+            ViewGroup parentGroup = (ViewGroup) mParent;
+            if (!parentGroup.translateBoundsAndIntersectionsInWindowCoordinates(
+                    this, bounds, intersections)) {
+                intersections.clear();
+                return false;
+            }
+        }
+
+        // Take into account the window location.
+        final int dx = mAttachInfo.mWindowLeft;
+        final int dy = mAttachInfo.mWindowTop;
+        bounds.offset(dx, dy);
+        offsetRects(intersections, dx, dy);
+
+        if (intersections.isEmpty() && interactiveRegion == null) {
+            outPoint.set((int) bounds.centerX(), (int) bounds.centerY());
+        } else {
+            // This view is partially covered by other views, then compute
+            // the not covered region and pick a point on its boundary.
+            Region region = new Region();
+            region.set((int) bounds.left, (int) bounds.top,
+                    (int) bounds.right, (int) bounds.bottom);
+
+            final int intersectionCount = intersections.size();
+            for (int i = intersectionCount - 1; i >= 0; i--) {
+                RectF intersection = intersections.remove(i);
+                region.op((int) intersection.left, (int) intersection.top,
+                        (int) intersection.right, (int) intersection.bottom,
+                        Region.Op.DIFFERENCE);
+            }
+
+            // If the view is completely covered, done.
+            if (region.isEmpty()) {
+                return false;
+            }
+
+            // Take into account the interactive portion of the window
+            // as the rest is covered by other windows. If no such a region
+            // then the whole window is interactive.
+            if (interactiveRegion != null) {
+                region.op(interactiveRegion, Region.Op.INTERSECT);
+            }
+
+            // If the view is completely covered, done.
+            if (region.isEmpty()) {
+                return false;
+            }
+
+            // Try a shortcut here.
+            if (region.isRect()) {
+                Rect regionBounds = mAttachInfo.mTmpInvalRect;
+                region.getBounds(regionBounds);
+                outPoint.set(regionBounds.centerX(), regionBounds.centerY());
+                return true;
+            }
+
+            // Get the a point on the region boundary path.
+            Path path = region.getBoundaryPath();
+            PathMeasure pathMeasure = new PathMeasure(path, false);
+            final float[] coordinates = mAttachInfo.mTmpTransformLocation;
+
+            // Without loss of generality pick a point.
+            final float point = pathMeasure.getLength() * 0.01f;
+            if (!pathMeasure.getPosTan(point, coordinates, null)) {
+                return false;
+            }
+
+            outPoint.set(Math.round(coordinates[0]), Math.round(coordinates[1]));
+        }
+
+        return true;
+    }
+
+    static void offsetRects(List<RectF> rects, float offsetX, float offsetY) {
+        final int rectCount = rects.size();
+        for (int i = 0; i < rectCount; i++) {
+            RectF intersection = rects.get(i);
+            intersection.offset(offsetX, offsetY);
+        }
+    }
+
+    /**
      * Returns the delegate for implementing accessibility support via
      * composition. For more details see {@link AccessibilityDelegate}.
      *
@@ -20154,6 +20286,16 @@
         final RectF mTmpTransformRect = new RectF();
 
         /**
+         * Temporary for use in computing hit areas with transformed views
+         */
+        final RectF mTmpTransformRect1 = new RectF();
+
+        /**
+         * Temporary list of rectanges.
+         */
+        final List<RectF> mTmpRectList = new ArrayList<>();
+
+        /**
          * Temporary for use in transforming invalidation rect
          */
         final Matrix mTmpMatrix = new Matrix();
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c1e66de..4e1db90 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -771,6 +771,112 @@
     }
 
     /**
+     * Translates the given bounds and intersections from child coordinates to
+     * local coordinates. In case any interactive sibling of the calling child
+     * covers the latter, a new intersections is added to the intersection list.
+     * This method is for the exclusive use by the accessibility layer to compute
+     * a point where a sequence of down and up events would click on a view.
+     *
+     * @param child The child making the call.
+     * @param bounds The bounds to translate in child coordinates.
+     * @param intersections The intersections of interactive views covering the child.
+     * @return True if the bounds and intersections were computed, false otherwise.
+     */
+    boolean translateBoundsAndIntersectionsInWindowCoordinates(View child,
+            RectF bounds, List<RectF> intersections) {
+        // Not attached, done.
+        if (mAttachInfo == null) {
+            return false;
+        }
+
+        if (getAlpha() <= 0 || getTransitionAlpha() <= 0 ||
+                getVisibility() != VISIBLE) {
+            // Cannot click on a view with an invisible predecessor.
+            return false;
+        }
+
+        // Compensate for the child transformation.
+        if (!child.hasIdentityMatrix()) {
+            Matrix matrix = child.getMatrix();
+            matrix.mapRect(bounds);
+            final int intersectionCount = intersections.size();
+            for (int i = 0; i < intersectionCount; i++) {
+                RectF intersection = intersections.get(i);
+                matrix.mapRect(intersection);
+            }
+        }
+
+        // Translate the bounds from child to parent coordinates.
+        final int dx = child.mLeft - mScrollX;
+        final int dy = child.mTop - mScrollY;
+        bounds.offset(dx, dy);
+        offsetRects(intersections, dx, dy);
+
+        // If the bounds do not intersect our bounds, done.
+        if (!bounds.intersects(0, 0, getWidth(), getHeight())) {
+            return false;
+        }
+
+        // Check whether any clickable siblings cover the child
+        // view and if so keep track of the intersections. Also
+        // respect Z ordering when iterating over children.
+        ArrayList<View> orderedList = buildOrderedChildList();
+        final boolean useCustomOrder = orderedList == null
+                && isChildrenDrawingOrderEnabled();
+
+        final int childCount = mChildrenCount;
+        for (int i = childCount - 1; i >= 0; i--) {
+            final int childIndex = useCustomOrder
+                    ? getChildDrawingOrder(childCount, i) : i;
+            final View sibling = (orderedList == null)
+                    ? mChildren[childIndex] : orderedList.get(childIndex);
+
+            // We care only about siblings over the child.
+            if (sibling == child) {
+                break;
+            }
+
+            // If sibling is not interactive we do not care.
+            if (!sibling.isClickable() && !sibling.isLongClickable()) {
+                continue;
+            }
+
+            // Compute the sibling bounds in its coordinates.
+            RectF siblingBounds = mAttachInfo.mTmpTransformRect1;
+            siblingBounds.set(0, 0, sibling.getWidth(), sibling.getHeight());
+
+            // Take into account the sibling transformation matrix.
+            if (!sibling.hasIdentityMatrix()) {
+                sibling.getMatrix().mapRect(siblingBounds);
+            }
+
+            // Offset the sibling to our coordinates.
+            final int siblingDx = sibling.mLeft - mScrollX;
+            final int siblingDy = sibling.mTop - mScrollY;
+            siblingBounds.offset(siblingDx, siblingDy);
+
+            // Compute the intersection between the child and the sibling.
+            if (siblingBounds.intersect(bounds)) {
+                // If an interactive sibling completely covers the child, done.
+                if (siblingBounds.equals(bounds)) {
+                    return false;
+                }
+                // Keep track of the intersection rectangle.
+                RectF intersection = new RectF(siblingBounds);
+                intersections.add(intersection);
+            }
+        }
+
+        if (mParent instanceof ViewGroup) {
+            ViewGroup parentGroup = (ViewGroup) mParent;
+            return parentGroup.translateBoundsAndIntersectionsInWindowCoordinates(
+                    this, bounds, intersections);
+        }
+
+        return true;
+    }
+
+    /**
      * Called when a child view has changed whether or not it is tracking transient state.
      */
     public void childHasTransientStateChanged(View child, boolean childHasTransientState) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4299e2e..80b9ade 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -6679,12 +6679,12 @@
         public void performAccessibilityAction(long accessibilityNodeId, int action,
                 Bundle arguments, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags,
-                int interogatingPid, long interrogatingTid) {
+                int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .performAccessibilityActionClientThread(accessibilityNodeId, action, arguments,
-                            interactionId, callback, flags, interogatingPid, interrogatingTid);
+                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -6696,6 +6696,26 @@
         }
 
         @Override
+        public void computeClickPointInScreen(long accessibilityNodeId, Region interactiveRegion,
+                int interactionId, IAccessibilityInteractionConnectionCallback callback,
+                int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
+            ViewRootImpl viewRootImpl = mViewRootImpl.get();
+            if (viewRootImpl != null && viewRootImpl.mView != null) {
+                viewRootImpl.getAccessibilityInteractionController()
+                        .computeClickPointInScreenClientThread(accessibilityNodeId,
+                                interactiveRegion, interactionId, callback, interrogatingPid,
+                                interrogatingTid, spec);
+            } else {
+                // We cannot make the call and notify the caller so it does not wait.
+                try {
+                    callback.setComputeClickPointInScreenActionResult(null, interactionId);
+                } catch (RemoteException re) {
+                    /* best effort - ignore */
+                }
+            }
+        }
+
+        @Override
         public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
                 String viewId, Region interactiveRegion, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags,
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index db78ec5..374f7e0 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -17,6 +17,7 @@
 package android.view.accessibility;
 
 import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.graphics.Point;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -98,6 +99,8 @@
 
     private boolean mPerformAccessibilityActionResult;
 
+    private Point mComputeClickPointResult;
+
     private Message mSameThreadMessage;
 
     private static final SparseArray<IAccessibilityServiceConnection> sConnectionCache =
@@ -519,6 +522,43 @@
         return false;
     }
 
+    /**
+     * Computes a point in screen coordinates where sending a down/up events would
+     * perform a click on an {@link AccessibilityNodeInfo}.
+     *
+     * @param connectionId The id of a connection for interacting with the system.
+     * @param accessibilityWindowId A unique window id. Use
+     *     {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+     *     to query the currently active window.
+     * @param accessibilityNodeId A unique view id or virtual descendant id from
+     *     where to start the search. Use
+     *     {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
+     *     to start from the root.
+     * @return Point the click point of null if no such point.
+     */
+    public Point computeClickPointInScreen(int connectionId, int accessibilityWindowId,
+            long accessibilityNodeId) {
+        try {
+            IAccessibilityServiceConnection connection = getConnection(connectionId);
+            if (connection != null) {
+                final int interactionId = mInteractionIdCounter.getAndIncrement();
+                final boolean success = connection.computeClickPointInScreen(
+                        accessibilityWindowId, accessibilityNodeId,
+                        interactionId, this, Thread.currentThread().getId());
+                if (success) {
+                    return getComputeClickPointInScreenResultAndClear(interactionId);
+                }
+            } else {
+                if (DEBUG) {
+                    Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+                }
+            }
+        } catch (RemoteException re) {
+            Log.w(LOG_TAG, "Error while calling remote computeClickPointInScreen", re);
+        }
+        return null;
+    }
+
     public void clearCache() {
         sAccessibilityCache.clear();
     }
@@ -634,6 +674,34 @@
     }
 
     /**
+     * Gets the result of a request to compute a point in screen for clicking on a node.
+     *
+     * @param interactionId The interaction id to match the result with the request.
+     * @return The point or null if no such point.
+     */
+    private Point getComputeClickPointInScreenResultAndClear(int interactionId) {
+        synchronized (mInstanceLock) {
+            final boolean success = waitForResultTimedLocked(interactionId);
+            Point result = success ? mComputeClickPointResult : null;
+            clearResultLocked();
+            return result;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setComputeClickPointInScreenActionResult(Point point, int interactionId) {
+        synchronized (mInstanceLock) {
+            if (interactionId > mInteractionId) {
+                mComputeClickPointResult = point;
+                mInteractionId = interactionId;
+            }
+            mInstanceLock.notifyAll();
+        }
+    }
+
+    /**
      * Clears the result state.
      */
     private void clearResultLocked() {
@@ -641,6 +709,7 @@
         mFindAccessibilityNodeInfoResult = null;
         mFindAccessibilityNodeInfosResult = null;
         mPerformAccessibilityActionResult = false;
+        mComputeClickPointResult = null;
     }
 
     /**
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index faf7789..66a3f46 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -17,6 +17,7 @@
 package android.view.accessibility;
 
 import android.graphics.Region;
+import android.graphics.Point;
 import android.os.Bundle;
 import android.view.MagnificationSpec;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -53,4 +54,8 @@
     void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments,
         int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
         int interrogatingPid, long interrogatingTid);
+
+    void computeClickPointInScreen(long accessibilityNodeId, in Region bounds, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
+        long interrogatingTid, in MagnificationSpec spec);
 }
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
index c1a3ab7..f480216 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
@@ -16,6 +16,7 @@
 
 package android.view.accessibility;
 
+import android.graphics.Point;
 import android.view.accessibility.AccessibilityNodeInfo;
 import java.util.List;
 
@@ -51,4 +52,12 @@
      * @param interactionId The interaction id to match the result with the request.
      */
     void setPerformAccessibilityActionResult(boolean succeeded, int interactionId);
+
+    /**
+     * Sets the result of a request to compute a point for clicking in a view.
+     *
+     * @param point The point of null if no such point.
+     * @param interactionId The interaction id to match the result with the request.
+     */
+    void setComputeClickPointInScreenActionResult(in Point point, int interactionId);
 }
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/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/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index 2382d18..8a66c3f 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -44,6 +44,7 @@
             android:layout_width="match_parent"
             android:layout_weight="1"
             android:layout_height="0dp"
+            android:layout_marginEnd="8dp"
             android:orientation="horizontal"
             >
             <TextView android:id="@+id/inbox_text0"
@@ -60,7 +61,6 @@
                 android:layout_height="@dimen/notification_badge_size"
                 android:layout_weight="0"
                 android:layout_marginStart="4dp"
-                android:layout_marginEnd="8dp"
                 android:scaleType="fitCenter"
                 android:visibility="gone"
                 />
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/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/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/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/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 082a158..2c805bb 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1109,9 +1109,9 @@
      * {@link #requestLocationUpdates(String, long, float, LocationListener)}.
      *
      * <p>
-     * Before API version 20, this method would throw {@link SecurityException}
-     * if the location permissions were not sufficient to use the specified
-     * provider.
+     * Before API version {@link android.os.Build.VERSION_CODES#L}, this
+     * method would throw {@link SecurityException} if the location permissions
+     * were not sufficient to use the specified provider.
      *
      * @param provider the name of the provider
      * @return true if the provider exists and is enabled
@@ -1119,7 +1119,6 @@
      * @throws IllegalArgumentException if provider is null
      */
     public boolean isProviderEnabled(String provider) {
-        // STOPSHIP: finalize API version number in javadoc
         checkProvider(provider);
 
         try {
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/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/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index 1ef9cad..4b68e77 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -23,6 +23,6 @@
     android:textSize="16sp"
     android:textColor="#ffffffff"
     android:text="@string/recents_empty_message"
-    android:fontFamily="sans-serif-light"
+    android:fontFamily="sans-serif"
     android:background="#80000000"
     android:visibility="gone" />
\ No newline at end of file
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..c0e2b10 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -134,10 +134,13 @@
     <integer name="recents_animate_task_exit_to_home_duration">225</integer>
     <!-- The min animation duration for animating the task bar out. -->
     <integer name="recents_animate_task_bar_exit_duration">125</integer>
+    <!-- The animation delay for animating the first task in. This should roughly be the animation
+     duration of the transition in to recents from home. -->
+    <integer name="recents_animate_task_enter_from_home_delay">150</integer>
     <!-- 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_stagger_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/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 5d8181c..396be3b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -74,8 +74,9 @@
     public float taskStackOverscrollPct;
 
     /** Task view animation and styles */
-    public int taskViewEnterFromHomeDuration;
     public int taskViewEnterFromHomeDelay;
+    public int taskViewEnterFromHomeDuration;
+    public int taskViewEnterFromHomeStaggerDelay;
     public int taskViewExitToHomeDuration;
     public int taskViewRemoveAnimDuration;
     public int taskViewRemoveAnimTranslationXPx;
@@ -209,10 +210,12 @@
         taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding);
 
         // Task view animation and styles
-        taskViewEnterFromHomeDuration =
-                res.getInteger(R.integer.recents_animate_task_enter_from_home_duration);
         taskViewEnterFromHomeDelay =
                 res.getInteger(R.integer.recents_animate_task_enter_from_home_delay);
+        taskViewEnterFromHomeDuration =
+                res.getInteger(R.integer.recents_animate_task_enter_from_home_duration);
+        taskViewEnterFromHomeStaggerDelay =
+                res.getInteger(R.integer.recents_animate_task_enter_from_home_stagger_delay);
         taskViewExitToHomeDuration =
                 res.getInteger(R.integer.recents_animate_task_exit_to_home_duration);
         taskViewRemoveAnimDuration =
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..6fe86be 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -284,7 +284,7 @@
                 float scaledWindowInsetTop = (int) (taskScale * windowInsetTop);
                 float scaledTranslationY = taskRect.top + transform.translationY -
                         (scaledWindowInsetTop + scaledYOffset);
-                startDelay = mConfig.taskViewEnterFromHomeDelay;
+                startDelay = mConfig.taskViewEnterFromHomeStaggerDelay;
 
                 // Animate the top clip
                 mViewBounds.animateClipTop(windowInsetTop, duration,
@@ -410,8 +410,8 @@
         } else if (mConfig.launchedFromHome) {
             // Animate the tasks up
             int frontIndex = (ctx.currentStackViewCount - ctx.currentStackViewIndex - 1);
-            int delay = mConfig.taskBarEnterAnimDelay +
-                    frontIndex * mConfig.taskViewEnterFromHomeDelay;
+            int delay = mConfig.taskViewEnterFromHomeDelay +
+                    frontIndex * mConfig.taskViewEnterFromHomeStaggerDelay;
             if (Constants.DebugFlags.App.EnableShadows) {
                 animate().translationZ(transform.translationZ);
             }
@@ -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/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 1c4556f..f4587db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -91,6 +91,7 @@
 import com.android.systemui.statusbar.phone.KeyguardTouchDelegate;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
+import com.android.systemui.statusbar.policy.PreviewInflater;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 import java.util.ArrayList;
@@ -260,10 +261,12 @@
             final boolean isActivity = pendingIntent.isActivity();
             if (isActivity) {
                 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
+                final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
+                        mContext, pendingIntent.getIntent(), mCurrentUserId);
                 dismissKeyguardThenExecute(new OnDismissAction() {
                     @Override
                     public boolean onDismiss() {
-                        if (keyguardShowing) {
+                        if (keyguardShowing && !afterKeyguardGone) {
                             try {
                                 ActivityManagerNative.getDefault()
                                         .keyguardWaitingForActivityDrawn();
@@ -277,7 +280,7 @@
                         }
 
                         boolean handled = superOnClickHandler(view, pendingIntent, fillInIntent);
-                        overrideActivityPendingAppTransition(keyguardShowing);
+                        overrideActivityPendingAppTransition(keyguardShowing && !afterKeyguardGone);
 
                         // close the shade if it was open
                         if (handled) {
@@ -287,7 +290,7 @@
                         // Wait for activity start.
                         return handled;
                     }
-                }, false /* afterKeyguardGone */);
+                }, afterKeyguardGone);
                 return true;
             } else {
                 return super.onClickHandler(view, pendingIntent, fillInIntent);
@@ -1440,6 +1443,9 @@
 
         public void onClick(final View v) {
             final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
+            final boolean afterKeyguardGone = mIntent.isActivity()
+                    && PreviewInflater.wouldLaunchResolverActivity(mContext, mIntent.getIntent(),
+                            mCurrentUserId);
             dismissKeyguardThenExecute(new OnDismissAction() {
                 public boolean onDismiss() {
                     if (mIsHeadsUp) {
@@ -1448,7 +1454,7 @@
                     AsyncTask.execute(new Runnable() {
                         @Override
                         public void run() {
-                            if (keyguardShowing) {
+                            if (keyguardShowing && !afterKeyguardGone) {
                                 try {
                                     ActivityManagerNative.getDefault()
                                             .keyguardWaitingForActivityDrawn();
@@ -1472,7 +1478,8 @@
                                     // TODO: Dismiss Keyguard.
                                 }
                                 if (mIntent.isActivity()) {
-                                    overrideActivityPendingAppTransition(keyguardShowing);
+                                    overrideActivityPendingAppTransition(keyguardShowing
+                                            && !afterKeyguardGone);
                                 }
                             }
 
@@ -1490,7 +1497,7 @@
 
                     return mIntent != null && mIntent.isActivity();
                 }
-            }, false /* afterKeyguardGone */);
+            }, afterKeyguardGone);
         }
     }
 
@@ -1625,7 +1632,7 @@
                 }
             }
             boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
-            if ((isLockscreenPublicMode() && !showOnKeyguard) ||
+            if ((isLockscreenPublicMode() && !mShowLockscreenNotifications) ||
                     (onKeyguard && (visibleNotifications >= maxKeyguardNotifications
                             || !showOnKeyguard))) {
                 entry.row.setVisibility(View.GONE);
@@ -1776,7 +1783,7 @@
                 oldEntry.notification.getNotification().tickerText);
 
         final boolean shouldInterrupt = shouldInterrupt(notification);
-        final boolean alertAgain = alertAgain(oldEntry);
+        final boolean alertAgain = alertAgain(oldEntry, n);
         boolean updateSuccessful = false;
         if (contentsUnchanged && bigContentsUnchanged && headsUpContentsUnchanged
                 && publicUnchanged) {
@@ -1940,10 +1947,9 @@
         }
     }
 
-    private boolean alertAgain(Entry entry) {
-        final StatusBarNotification sbn = entry.notification;
-        return entry == null || !entry.hasInterrupted()
-                || (sbn.getNotification().flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
+    private boolean alertAgain(Entry oldEntry, Notification newNotification) {
+        return oldEntry == null || !oldEntry.hasInterrupted()
+                || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
     }
 
     protected boolean shouldInterrupt(StatusBarNotification sbn) {
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/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
index 9dfbb27..23810f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
@@ -24,5 +24,5 @@
  * Keyguard.
  */
 public interface ActivityStarter {
-    public void startActivity(Intent intent, boolean dismissShade, boolean afterKeyguardGone);
+    public void startActivity(Intent intent, boolean dismissShade);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index f9da30f..e84ca52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -315,15 +315,15 @@
     public void launchCamera() {
         mFlashlightController.killFlashlight();
         Intent intent = getCameraIntent();
-        boolean wouldLaunchResolverActivity = mPreviewInflater.wouldLaunchResolverActivity(intent);
+        boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
+                mContext, intent, mLockPatternUtils.getCurrentUser());
         if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
             mContext.startActivityAsUser(intent, UserHandle.CURRENT);
         } else {
 
             // We need to delay starting the activity because ResolverActivity finishes itself if
             // launched behind lockscreen.
-            mActivityStarter.startActivity(intent, false /* dismissShade */,
-                    wouldLaunchResolverActivity /* afterKeyguardGone */);
+            mActivityStarter.startActivity(intent, false /* dismissShade */);
         }
     }
 
@@ -337,8 +337,7 @@
                 }
             });
         } else {
-            mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */,
-                    mPreviewInflater.wouldLaunchResolverActivity(PHONE_INTENT));
+            mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */);
         }
     }
 
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 861bf4a..128c687 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -149,6 +149,7 @@
 import com.android.systemui.statusbar.policy.LocationControllerImpl;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl;
 import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.PreviewInflater;
 import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
 import com.android.systemui.statusbar.policy.SecurityControllerImpl;
 import com.android.systemui.statusbar.policy.UserInfoController;
@@ -786,8 +787,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) {
@@ -2067,8 +2071,8 @@
     }
 
     @Override
-    public void startActivity(Intent intent, boolean dismissShade, boolean afterKeyguardGone) {
-        startActivityDismissingKeyguard(intent, false, dismissShade, afterKeyguardGone);
+    public void startActivity(Intent intent, boolean dismissShade) {
+        startActivityDismissingKeyguard(intent, false, dismissShade);
     }
 
     public ScrimController getScrimController() {
@@ -2957,9 +2961,11 @@
     }
 
     public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
-            final boolean dismissShade, final boolean afterKeyguardGone) {
+            final boolean dismissShade) {
         if (onlyProvisioned && !isDeviceProvisioned()) return;
 
+        final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
+                mContext, intent, mCurrentUserId);
         final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
         dismissKeyguardThenExecute(new OnDismissAction() {
             @Override
@@ -3308,8 +3314,7 @@
     }
 
     private void handleStartSettingsActivity(Intent intent, boolean onlyProvisioned) {
-        startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */,
-                false /* afterKeyguardGone */);
+        startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */);
     }
 
     private static class FastColorDrawable extends Drawable {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index eeb97e3..15a7229 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -497,20 +497,19 @@
         } else if (v == mAlarmStatus && mNextAlarm != null) {
             PendingIntent showIntent = mNextAlarm.getShowIntent();
             if (showIntent != null && showIntent.isActivity()) {
-                mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */,
-                        false /* afterKeyguardGone */);
+                mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */);
             }
         }
     }
 
     private void startSettingsActivity() {
         mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
-                true /* dismissShade */, false /* afterKeyguardGone */);
+                true /* dismissShade */);
     }
 
     private void startBatteryActivity() {
         mActivityStarter.startActivity(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY),
-                true /* dismissShade */, false /* afterKeyguardGone */);
+                true /* dismissShade */);
     }
 
     public void setQSPanel(QSPanel qsp) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 4a6f1a8..f04d6a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -928,8 +928,8 @@
                     intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
             boolean wasConnected = mWifiConnected;
             mWifiConnected = networkInfo != null && networkInfo.isConnected();
-            // If we just connected, grab the inintial signal strength and ssid
-            if (mWifiConnected && !wasConnected) {
+            // If Connected grab the signal strength and ssid
+            if (mWifiConnected) {
                 // try getting it out of the intent first
                 WifiInfo info = (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
                 if (info == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
index cdbe494..030cd6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
@@ -20,14 +20,12 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
 import android.os.UserHandle;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 
 import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardActivityLauncher;
 import com.android.systemui.statusbar.phone.KeyguardPreviewContainer;
 
 import java.util.List;
@@ -107,20 +105,21 @@
         return info;
     }
 
-    public boolean wouldLaunchResolverActivity(Intent intent) {
-        PackageManager packageManager = mContext.getPackageManager();
+    public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent,
+            int currentUserId) {
+        PackageManager packageManager = ctx.getPackageManager();
         final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
-                intent, PackageManager.MATCH_DEFAULT_ONLY, mLockPatternUtils.getCurrentUser());
+                intent, PackageManager.MATCH_DEFAULT_ONLY, currentUserId);
         if (appList.size() == 0) {
             return false;
         }
         ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
-                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
-                mLockPatternUtils.getCurrentUser());
+                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, currentUserId);
         return wouldLaunchResolverActivity(resolved, appList);
     }
 
-    private boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) {
+    private static boolean wouldLaunchResolverActivity(
+            ResolveInfo resolved, List<ResolveInfo> appList) {
         // If the list contains the above resolved activity, then it can't be
         // ResolverActivity itself.
         for (int i = 0; i < appList.size(); i++) {
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/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index acb4827..0586a83 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -140,8 +140,7 @@
         @Override
         public void run() {
             getComponent(PhoneStatusBar.class).startActivityDismissingKeyguard(
-                    ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */,
-                    false /* afterKeyguardGone */);
+                    ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */);
             mPanel.postDismiss(mDismissDelay);
         }
     };
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index a43a2a6..ebe21ff 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -746,14 +746,16 @@
     }
 
     /**
-     * Gets the bounds of the accessibility focus in the active window.
+     * Gets a point within the accessibility focused node where we can send down
+     * and up events to perform a click.
      *
-     * @param outBounds The output to which to write the focus bounds.
-     * @return Whether accessibility focus was found and the bounds are populated.
+     * @param outPoint The click point to populate.
+     * @return Whether accessibility a click point was found and set.
      */
     // TODO: (multi-display) Make sure this works for multiple displays.
-    boolean getAccessibilityFocusBounds(Rect outBounds) {
-        return getInteractionBridgeLocked().getAccessibilityFocusBoundsNotLocked(outBounds);
+    boolean getAccessibilityFocusClickPointInScreen(Point outPoint) {
+        return getInteractionBridgeLocked()
+                .getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
     }
 
     /**
@@ -2196,8 +2198,8 @@
             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
                 connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName,
-                        partialInteractiveRegion, interactionId, callback, mFetchFlags, interrogatingPid,
-                        interrogatingTid, spec);
+                        partialInteractiveRegion, interactionId, callback, mFetchFlags,
+                        interrogatingPid, interrogatingTid, spec);
                 return true;
             } catch (RemoteException re) {
                 if (DEBUG) {
@@ -2248,8 +2250,8 @@
             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
                 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
-                        partialInteractiveRegion, interactionId, callback, mFetchFlags, interrogatingPid,
-                        interrogatingTid, spec);
+                        partialInteractiveRegion, interactionId, callback, mFetchFlags,
+                        interrogatingPid, interrogatingTid, spec);
                 return true;
             } catch (RemoteException re) {
                 if (DEBUG) {
@@ -2352,8 +2354,9 @@
             final long identityToken = Binder.clearCallingIdentity();
             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
-                connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion, interactionId,
-                        callback, mFetchFlags, interrogatingPid, interrogatingTid, spec);
+                connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion,
+                        interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
+                        spec);
                 return true;
             } catch (RemoteException re) {
                 if (DEBUG) {
@@ -2403,8 +2406,9 @@
             final long identityToken = Binder.clearCallingIdentity();
             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
-                connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion, interactionId,
-                        callback, mFetchFlags, interrogatingPid, interrogatingTid, spec);
+                connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion,
+                        interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
+                        spec);
                 return true;
             } catch (RemoteException re) {
                 if (DEBUG) {
@@ -2460,6 +2464,7 @@
             return true;
         }
 
+        @Override
         public boolean performGlobalAction(int action) {
             synchronized (mLock) {
                 // We treat calls from a profile as if made by its parent as profiles
@@ -2501,6 +2506,57 @@
         }
 
         @Override
+        public  boolean computeClickPointInScreen(int accessibilityWindowId,
+                long accessibilityNodeId, int interactionId,
+                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
+                throws RemoteException {
+            final int resolvedWindowId;
+            IAccessibilityInteractionConnection connection = null;
+            Region partialInteractiveRegion = mTempRegion;
+            synchronized (mLock) {
+                // We treat calls from a profile as if made by its parent as profiles
+                // share the accessibility state of the parent. The call below
+                // performs the current profile parent resolution.
+                final int resolvedUserId = mSecurityPolicy
+                        .resolveCallingUserIdEnforcingPermissionsLocked(
+                                UserHandle.getCallingUserId());
+                if (resolvedUserId != mCurrentUserId) {
+                    return false;
+                }
+                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
+                final boolean permissionGranted =
+                        mSecurityPolicy.canRetrieveWindowContentLocked(this);
+                if (!permissionGranted) {
+                    return false;
+                } else {
+                    connection = getConnectionLocked(resolvedWindowId);
+                    if (connection == null) {
+                        return false;
+                    }
+                }
+                if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
+                        resolvedWindowId, partialInteractiveRegion)) {
+                    partialInteractiveRegion = null;
+                }
+            }
+            final int interrogatingPid = Binder.getCallingPid();
+            final long identityToken = Binder.clearCallingIdentity();
+            MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
+            try {
+                connection.computeClickPointInScreen(accessibilityNodeId, partialInteractiveRegion,
+                        interactionId, callback, interrogatingPid, interrogatingTid, spec);
+                return true;
+            } catch (RemoteException re) {
+                if (DEBUG) {
+                    Slog.e(LOG_TAG, "Error computeClickPointInScreen().");
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identityToken);
+            }
+            return false;
+        }
+
+        @Override
         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
             mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
             synchronized (mLock) {
@@ -3119,30 +3175,43 @@
             }
         }
 
-        public boolean getAccessibilityFocusBoundsNotLocked(Rect outBounds) {
+        public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) {
             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
             if (focus == null) {
                 return false;
             }
 
             synchronized (mLock) {
-                focus.getBoundsInScreen(outBounds);
+                Point point = mClient.computeClickPointInScreen(mConnectionId,
+                        focus.getWindowId(), focus.getSourceNodeId());
+
+                if (point == null) {
+                    return false;
+                }
 
                 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
                 if (spec != null && !spec.isNop()) {
-                    outBounds.offset((int) -spec.offsetX, (int) -spec.offsetY);
-                    outBounds.scale(1 / spec.scale);
+                    point.offset((int) -spec.offsetX, (int) -spec.offsetY);
+                    point.x = (int) (point.x * (1 / spec.scale));
+                    point.y = (int) (point.y * (1 / spec.scale));
                 }
 
-                // Clip to the window rectangle.
+                // Make sure the point is within the window.
                 Rect windowBounds = mTempRect;
                 getActiveWindowBounds(windowBounds);
-                outBounds.intersect(windowBounds);
+                if (!windowBounds.contains(point.x, point.y)) {
+                    return false;
+                }
 
-                // Clip to the screen rectangle.
-                mDefaultDisplay.getRealSize(mTempPoint);
-                outBounds.intersect(0, 0, mTempPoint.x, mTempPoint.y);
+                // Make sure the point is within the screen.
+                Point screenSize = mTempPoint;
+                mDefaultDisplay.getRealSize(screenSize);
+                if (point.x < 0 || point.x > screenSize.x
+                        || point.y < 0 || point.y > screenSize.y) {
+                    return false;
+                }
 
+                outPoint.set(point.x, point.y);
                 return true;
             }
         }
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index ac0ca0a..9e63433 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -24,6 +24,7 @@
 import android.gesture.GestureStore;
 import android.gesture.GestureStroke;
 import android.gesture.Prediction;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.SystemClock;
@@ -171,6 +172,9 @@
     // Temporary rectangle to avoid instantiation.
     private final Rect mTempRect = new Rect();
 
+    // Temporary point to avoid instantiation.
+    private final Point mTempPoint = new Point();
+
     // Context in which this explorer operates.
     private final Context mContext;
 
@@ -1157,18 +1161,18 @@
                 mInjectedPointerTracker.getLastInjectedHoverEventForClick();
             if (lastExploreEvent == null) {
                 // No last touch explored event but there is accessibility focus in
-                // the active window. We click in the middle of the focus bounds.
-                Rect focusBounds = mTempRect;
-                if (mAms.getAccessibilityFocusBounds(focusBounds)) {
-                    clickLocationX = focusBounds.centerX();
-                    clickLocationY = focusBounds.centerY();
+                // the active window. We click in the focus bounds.
+                Point point = mTempPoint;
+                if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
+                    clickLocationX = point.x;
+                    clickLocationY = point.y;
                 } else {
                     // Out of luck - do nothing.
                     return;
                 }
             } else {
                 // If the click is within the active window but not within the
-                // accessibility focus bounds we click in the focus center.
+                // accessibility focus bounds we click in the focus bounds.
                 final int lastExplorePointerIndex = lastExploreEvent.getActionIndex();
                 clickLocationX = (int) lastExploreEvent.getX(lastExplorePointerIndex);
                 clickLocationY = (int) lastExploreEvent.getY(lastExplorePointerIndex);
@@ -1176,12 +1180,10 @@
                 if (mLastTouchedWindowId == mAms.getActiveWindowId()) {
                     mAms.getActiveWindowBounds(activeWindowBounds);
                     if (activeWindowBounds.contains(clickLocationX, clickLocationY)) {
-                        Rect focusBounds = mTempRect;
-                        if (mAms.getAccessibilityFocusBounds(focusBounds)) {
-                            if (!focusBounds.contains(clickLocationX, clickLocationY)) {
-                                clickLocationX = focusBounds.centerX();
-                                clickLocationY = focusBounds.centerY();
-                            }
+                        Point point = mTempPoint;
+                        if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
+                            clickLocationX = point.x;
+                            clickLocationY = point.y;
                         }
                     }
                 }
@@ -1330,18 +1332,18 @@
                 mInjectedPointerTracker.getLastInjectedHoverEventForClick();
             if (lastExploreEvent == null) {
                 // No last touch explored event but there is accessibility focus in
-                // the active window. We click in the middle of the focus bounds.
-                Rect focusBounds = mTempRect;
-                if (mAms.getAccessibilityFocusBounds(focusBounds)) {
-                    clickLocationX = focusBounds.centerX();
-                    clickLocationY = focusBounds.centerY();
+                // the active window. We click in the focus bounds.
+                Point point = mTempPoint;
+                if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
+                    clickLocationX = point.x;
+                    clickLocationY = point.y;
                 } else {
                     // Out of luck - do nothing.
                     return;
                 }
             } else {
                 // If the click is within the active window but not within the
-                // accessibility focus bounds we click in the focus center.
+                // accessibility focus bounds we click in the focus bounds.
                 final int lastExplorePointerIndex = lastExploreEvent.getActionIndex();
                 clickLocationX = (int) lastExploreEvent.getX(lastExplorePointerIndex);
                 clickLocationY = (int) lastExploreEvent.getY(lastExplorePointerIndex);
@@ -1349,12 +1351,10 @@
                 if (mLastTouchedWindowId == mAms.getActiveWindowId()) {
                     mAms.getActiveWindowBounds(activeWindowBounds);
                     if (activeWindowBounds.contains(clickLocationX, clickLocationY)) {
-                        Rect focusBounds = mTempRect;
-                        if (mAms.getAccessibilityFocusBounds(focusBounds)) {
-                            if (!focusBounds.contains(clickLocationX, clickLocationY)) {
-                                clickLocationX = focusBounds.centerX();
-                                clickLocationY = focusBounds.centerY();
-                            }
+                        Point point = mTempPoint;
+                        if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
+                            clickLocationX = point.x;
+                            clickLocationY = point.y;
                         }
                     }
                 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6ddad41..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);
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..b8261a4 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) {
@@ -2779,9 +2783,8 @@
         }
 
         // A non-top activity is reporting a visibility change.
-        if ((visible && (top.fullscreen || top.state != ActivityState.RESUMED)) ||
-                top.app == null || top.app.thread == null) {
-            // Can't carry out this request.
+        if (visible && top.fullscreen) {
+            // Let the caller know that it can't be seen.
             if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind: returning top.fullscreen="
                     + top.fullscreen + " top.state=" + top.state + " top.app=" + top.app +
                     " top.app.thread=" + top.app.thread);
@@ -2803,9 +2806,12 @@
                 mService.convertFromTranslucent(next.appToken);
             }
         }
-        try {
-            top.app.thread.scheduleBackgroundVisibleBehindChanged(top.appToken, visible);
-        } catch (RemoteException e) {
+        if (top.app != null && top.app.thread != null) {
+            // Notify the top app of the change.
+            try {
+                top.app.thread.scheduleBackgroundVisibleBehindChanged(top.appToken, visible);
+            } catch (RemoteException e) {
+            }
         }
         return true;
     }
@@ -3840,7 +3846,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/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 54f043d..a56f783 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2648,6 +2648,11 @@
             if (speedBumpIndex == -1 &&
                     // Intrusiveness trumps priority, hence ignore intrusives.
                     !record.isRecentlyIntrusive() &&
+                    // Currently, package priority is either PRIORITY_DEFAULT or PRIORITY_MAX, so
+                    // scanning for PRIORITY_MIN within the package bucket PRIORITY_DEFAULT
+                    // (or lower as a safeguard) is sufficient to find the speedbump index.
+                    // We'll have to revisit this when more package priority buckets are introduced.
+                    record.getPackagePriority() <= Notification.PRIORITY_DEFAULT &&
                     record.sbn.getNotification().priority == Notification.PRIORITY_MIN) {
                 speedBumpIndex = keys.size() - 1;
             }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 168328f..5639dad 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -18,7 +18,6 @@
 
 import static android.media.AudioAttributes.USAGE_ALARM;
 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
-import static android.media.AudioAttributes.USAGE_UNKNOWN;
 
 import android.app.AppOpsManager;
 import android.app.Notification;
@@ -225,11 +224,6 @@
                 muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
                 exceptionPackages);
 
-        // restrict vibrations with no hints
-        mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, USAGE_UNKNOWN,
-                zen ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                exceptionPackages);
-
         // alarm restrictions
         final boolean muteAlarms = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
         mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, USAGE_ALARM,
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 89ea905..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
@@ -1031,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 f8273c0..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.active = 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,15 +854,35 @@
         }
     }
 
-    public void open() {
-        if (mOpenCount.getAndIncrement() == 0) {
+    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) {
+        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/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/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/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/Conference.java b/telecomm/java/android/telecomm/Conference.java
index c838b48..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;
     }
 
@@ -183,7 +183,7 @@
     }
 
     /**
-     * Tears down the conference object and any of it's current connections.
+     * Tears down the conference object and any of its current connections.
      */
     public final void destroy() {
         Log.d(this, "destroying conference : %s", this);
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 833aa26..39365b6 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -781,7 +781,7 @@
                 }
             }
             ParcelableConference parcelableConference = new ParcelableConference(
-                    conference.getPhoneAccount(),
+                    conference.getPhoneAccountHandle(),
                     conference.getState(),
                     conference.getCapabilities(),
                     connectionIds);
diff --git a/telecomm/java/android/telecomm/PhoneAccount.java b/telecomm/java/android/telecomm/PhoneAccount.java
index 1d61a6e..d3da2ec 100644
--- a/telecomm/java/android/telecomm/PhoneAccount.java
+++ b/telecomm/java/android/telecomm/PhoneAccount.java
@@ -98,8 +98,8 @@
     public static final String SCHEME_SIP = "sip";
 
     private final PhoneAccountHandle mAccountHandle;
-    private final Uri mHandle;
-    private final String mSubscriptionNumber;
+    private final Uri mAddress;
+    private final Uri mSubscriptionAddress;
     private final int mCapabilities;
     private final int mIconResId;
     private final CharSequence mLabel;
@@ -108,47 +108,40 @@
 
     public static class Builder {
         private PhoneAccountHandle mAccountHandle;
-        private Uri mHandle;
-        private String mSubscriptionNumber;
+        private Uri mAddress;
+        private Uri mSubscriptionAddress;
         private int mCapabilities;
         private int mIconResId;
         private CharSequence mLabel;
         private CharSequence mShortDescription;
         private List<String> mSupportedUriSchemes = new ArrayList<String>();
 
-        public Builder() {}
+        public Builder(PhoneAccountHandle accountHandle, CharSequence label) {
+            this.mAccountHandle = accountHandle;
+            this.mLabel = label;
+        }
 
-        public Builder withAccountHandle(PhoneAccountHandle value) {
-            this.mAccountHandle = value;
+        public Builder setAddress(Uri value) {
+            this.mAddress = value;
             return this;
         }
 
-        public Builder withHandle(Uri value) {
-            this.mHandle = value;
+        public Builder setSubscriptionAddress(Uri value) {
+            this.mSubscriptionAddress = value;
             return this;
         }
 
-        public Builder withSubscriptionNumber(String value) {
-            this.mSubscriptionNumber = value;
-            return this;
-        }
-
-        public Builder withCapabilities(int value) {
+        public Builder setCapabilities(int value) {
             this.mCapabilities = value;
             return this;
         }
 
-        public Builder withIconResId(int value) {
+        public Builder setIconResId(int value) {
             this.mIconResId = value;
             return this;
         }
 
-        public Builder withLabel(CharSequence value) {
-            this.mLabel = value;
-            return this;
-        }
-
-        public Builder withShortDescription(CharSequence value) {
+        public Builder setShortDescription(CharSequence value) {
             this.mShortDescription = value;
             return this;
         }
@@ -158,8 +151,9 @@
          *
          * @param uriScheme The URI scheme.
          * @return The Builder.
+         * @hide
          */
-        public Builder withSupportedUriScheme(String uriScheme) {
+        public Builder addSupportedUriScheme(String uriScheme) {
             if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
                 this.mSupportedUriSchemes.add(uriScheme);
             }
@@ -167,15 +161,17 @@
         }
 
         /**
-         * Specifies additional URI schemes supported by the {@link PhoneAccount}.
+         * Specifies the URI schemes supported by the {@link PhoneAccount}.
          *
          * @param uriSchemes The URI schemes.
          * @return The Builder.
          */
-        public Builder withSupportedUriSchemes(List<String> uriSchemes) {
+        public Builder setSupportedUriSchemes(List<String> uriSchemes) {
+            mSupportedUriSchemes.clear();
+
             if (uriSchemes != null && !uriSchemes.isEmpty()) {
                 for (String uriScheme : uriSchemes) {
-                    withSupportedUriScheme(uriScheme);
+                    addSupportedUriScheme(uriScheme);
                 }
             }
             return this;
@@ -184,13 +180,13 @@
         public PhoneAccount build() {
             // If no supported URI schemes were defined, assume "tel" is supported.
             if (mSupportedUriSchemes.isEmpty()) {
-                withSupportedUriScheme(SCHEME_TEL);
+                addSupportedUriScheme(SCHEME_TEL);
             }
 
             return new PhoneAccount(
                     mAccountHandle,
-                    mHandle,
-                    mSubscriptionNumber,
+                    mAddress,
+                    mSubscriptionAddress,
                     mCapabilities,
                     mIconResId,
                     mLabel,
@@ -201,16 +197,16 @@
 
     private PhoneAccount(
             PhoneAccountHandle account,
-            Uri handle,
-            String subscriptionNumber,
+            Uri address,
+            Uri subscriptionAddress,
             int capabilities,
             int iconResId,
             CharSequence label,
             CharSequence shortDescription,
             List<String> supportedUriSchemes) {
         mAccountHandle = account;
-        mHandle = handle;
-        mSubscriptionNumber = subscriptionNumber;
+        mAddress = address;
+        mSubscriptionAddress = subscriptionAddress;
         mCapabilities = capabilities;
         mIconResId = iconResId;
         mLabel = label;
@@ -218,7 +214,11 @@
         mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
     }
 
-    public static Builder builder() { return new Builder(); }
+    public static Builder builder(
+            PhoneAccountHandle accountHandle,
+            CharSequence label) {
+        return new Builder(accountHandle, label);
+    }
 
     /**
      * The unique identifier of this {@code PhoneAccount}.
@@ -230,32 +230,30 @@
     }
 
     /**
-     * The handle (e.g., a phone number) associated with this {@code PhoneAccount}. This
+     * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This
      * represents the destination from which outgoing calls using this {@code PhoneAccount}
      * will appear to come, if applicable, and the destination to which incoming calls using this
      * {@code PhoneAccount} may be addressed.
      *
-     * @return A handle expressed as a {@code Uri}, for example, a phone number.
+     * @return A address expressed as a {@code Uri}, for example, a phone number.
      */
-    public Uri getHandle() {
-        return mHandle;
+    public Uri getAddress() {
+        return mAddress;
     }
 
     /**
      * The raw callback number used for this {@code PhoneAccount}, as distinct from
-     * {@link #getHandle()}. For the majority of {@code PhoneAccount}s this should be registered
+     * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered
      * as {@code null}.  It is used by the system for SIM-based {@code PhoneAccount} registration
      * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)}
      * or {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(long, String, String)}
      * has been used to alter the callback number.
      * <p>
-     * TODO: Should this also be a URI, for consistency? Should it be called the
-     * "subscription handle"?
      *
      * @return The subscription number, suitable for display to the user.
      */
-    public String getSubscriptionNumber() {
-        return mSubscriptionNumber;
+    public Uri getSubscriptionAddress() {
+        return mSubscriptionAddress;
     }
 
     /**
@@ -295,11 +293,11 @@
     }
 
     /**
-     * Determines if the {@link PhoneAccount} supports calls to/from handles with a specified URI
+     * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
      * scheme.
      *
      * @param uriScheme The URI scheme to check.
-     * @return {@code True} if the {@code PhoneAccount} supports calls to/from handles with the
+     * @return {@code True} if the {@code PhoneAccount} supports calls to/from addresses with the
      * specified URI scheme.
      */
     public boolean supportsUriScheme(String uriScheme) {
@@ -363,8 +361,8 @@
     @Override
     public void writeToParcel(Parcel out, int flags) {
         out.writeParcelable(mAccountHandle, 0);
-        out.writeParcelable(mHandle, 0);
-        out.writeString(mSubscriptionNumber);
+        out.writeParcelable(mAddress, 0);
+        out.writeParcelable(mSubscriptionAddress, 0);
         out.writeInt(mCapabilities);
         out.writeInt(mIconResId);
         out.writeCharSequence(mLabel);
@@ -389,8 +387,8 @@
         ClassLoader classLoader = PhoneAccount.class.getClassLoader();
 
         mAccountHandle = in.readParcelable(getClass().getClassLoader());
-        mHandle = in.readParcelable(getClass().getClassLoader());
-        mSubscriptionNumber = in.readString();
+        mAddress = in.readParcelable(getClass().getClassLoader());
+        mSubscriptionAddress = in.readParcelable(getClass().getClassLoader());
         mCapabilities = in.readInt();
         mIconResId = in.readInt();
         mLabel = in.readCharSequence();
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 79193c2..8ad0ad0 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -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/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/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
     }
 
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index ac2a176..21f200f 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -341,6 +341,12 @@
 
     /**
      * @hide
+     * last time we connected, this configuration had no internet access
+     */
+    public boolean noInternetAccess;
+
+    /**
+     * @hide
      * Uid of app creating the configuration
      */
     @SystemApi
@@ -673,6 +679,49 @@
     @SystemApi
     public int numAssociation;
 
+    /**
+     * @hide
+     * Number of time user disabled WiFi while associated to this configuration with Low RSSI.
+     */
+    public int numUserTriggeredWifiDisableLowRSSI;
+
+    /**
+     * @hide
+     * Number of time user disabled WiFi while associated to this configuration with Bad RSSI.
+     */
+    public int numUserTriggeredWifiDisableBadRSSI;
+
+    /**
+     * @hide
+     * Number of time user disabled WiFi while associated to this configuration
+     * and RSSI was not HIGH.
+     */
+    public int numUserTriggeredWifiDisableNotHighRSSI;
+
+    /**
+     * @hide
+     * Number of ticks associated to this configuration with Low RSSI.
+     */
+    public int numTicksAtLowRSSI;
+
+    /**
+     * @hide
+     * Number of ticks associated to this configuration with Bad RSSI.
+     */
+    public int numTicksAtBadRSSI;
+
+    /**
+     * @hide
+     * Number of ticks associated to this configuration
+     * and RSSI was not HIGH.
+     */
+    public int numTicksAtNotHighRSSI;
+    /**
+     * @hide
+     * Number of time user (WifiManager) triggered association to this configuration.
+     * TODO: count this only for Wifi Settings uuid, so as to not count 3rd party apps
+     */
+    public int numUserTriggeredJoinAttempts;
 
     /**
      * @hide
@@ -725,6 +774,7 @@
         selfAdded = false;
         didSelfAdd = false;
         ephemeral = false;
+        noInternetAccess = false;
         mIpConfiguration = new IpConfiguration();
     }
 
@@ -824,8 +874,10 @@
             sbuf.append(" autoJoinStatus ").append(this.numConnectionFailures).append("\n");
         }
         if (this.didSelfAdd || this.selfAdded) {
-            if (this.didSelfAdd) sbuf.append(" didSelfAdd ");
-            if (this.selfAdded) sbuf.append(" selfAdded ");
+            if (this.didSelfAdd) sbuf.append(" didSelfAdd");
+            if (this.selfAdded) sbuf.append(" selfAdded");
+            if (this.noInternetAccess) sbuf.append(" noInternetAccess");
+
             sbuf.append("\n");
         }
         sbuf.append(" KeyMgmt:");
@@ -896,18 +948,44 @@
 
         sbuf.append(mIpConfiguration.toString());
 
-        if (selfAdded)  sbuf.append("selfAdded");
-        if (creatorUid != 0)  sbuf.append("uid=" + Integer.toString(creatorUid));
+        if (this.creatorUid != 0)  sbuf.append("uid=" + Integer.toString(creatorUid));
 
-        if (blackListTimestamp != 0) {
+        if (this.blackListTimestamp != 0) {
             long now_ms = System.currentTimeMillis();
-            long diff = now_ms - blackListTimestamp;
+            long diff = now_ms - this.blackListTimestamp;
             if (diff <= 0) {
                 sbuf.append("blackListed since <incorrect>");
             } else {
                 sbuf.append("blackListed since ").append(Long.toString(diff/1000)).append( "sec");
             }
         }
+        sbuf.append('\n');
+        if (this.linkedConfigurations != null) {
+            for(String key : this.linkedConfigurations.keySet()) {
+                sbuf.append(" linked: ").append(key);
+                sbuf.append('\n');
+            }
+        }
+        if (this.connectChoices != null) {
+            for(String key : this.connectChoices.keySet()) {
+                Integer choice = this.connectChoices.get(key);
+                if (choice != null) {
+                    sbuf.append(" choice: ").append(key);
+                    sbuf.append(" = ").append(choice);
+                    sbuf.append('\n');
+                }
+            }
+        }
+        sbuf.append(" triggeredLow: ").append(numUserTriggeredWifiDisableLowRSSI);
+        sbuf.append(" triggeredBad: ").append(numUserTriggeredWifiDisableBadRSSI);
+        sbuf.append(" triggeredNotHigh: ").append(numUserTriggeredWifiDisableNotHighRSSI);
+        sbuf.append('\n');
+        sbuf.append(" ticksLow: ").append(numTicksAtLowRSSI);
+        sbuf.append(" ticksBad: ").append(numTicksAtBadRSSI);
+        sbuf.append(" ticksNotHigh: ").append(numTicksAtNotHighRSSI);
+        sbuf.append('\n');
+        sbuf.append(" triggeredJoin: ").append(numUserTriggeredJoinAttempts);
+        sbuf.append('\n');
 
         return sbuf.toString();
     }
@@ -1197,7 +1275,7 @@
             mCachedConfigKey = null; //force null configKey
             autoJoinStatus = source.autoJoinStatus;
             selfAdded = source.selfAdded;
-
+            noInternetAccess = source.noInternetAccess;
             if (source.visibility != null) {
                 visibility = new Visibility(source.visibility);
             }
@@ -1217,6 +1295,13 @@
             numScorerOverride = source.numScorerOverride;
             numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
             numAssociation = source.numAssociation;
+            numUserTriggeredWifiDisableLowRSSI = source.numUserTriggeredWifiDisableLowRSSI;
+            numUserTriggeredWifiDisableBadRSSI = source.numUserTriggeredWifiDisableBadRSSI;
+            numUserTriggeredWifiDisableNotHighRSSI = source.numUserTriggeredWifiDisableNotHighRSSI;
+            numTicksAtLowRSSI = source.numTicksAtLowRSSI;
+            numTicksAtBadRSSI = source.numTicksAtBadRSSI;
+            numTicksAtNotHighRSSI = source.numTicksAtNotHighRSSI;
+            numUserTriggeredJoinAttempts = source.numUserTriggeredJoinAttempts;
         }
     }
 
@@ -1259,6 +1344,7 @@
         dest.writeInt(autoJoinStatus);
         dest.writeInt(selfAdded ? 1 : 0);
         dest.writeInt(didSelfAdd ? 1 : 0);
+        dest.writeInt(noInternetAccess ? 1 : 0);
         dest.writeInt(creatorUid);
         dest.writeInt(lastConnectUid);
         dest.writeInt(lastUpdateUid);
@@ -1269,6 +1355,14 @@
         dest.writeInt(numScorerOverride);
         dest.writeInt(numScorerOverrideAndSwitchedNetwork);
         dest.writeInt(numAssociation);
+        dest.writeInt(numUserTriggeredWifiDisableLowRSSI);
+        dest.writeInt(numUserTriggeredWifiDisableBadRSSI);
+        dest.writeInt(numUserTriggeredWifiDisableNotHighRSSI);
+        dest.writeInt(numTicksAtLowRSSI);
+        dest.writeInt(numTicksAtBadRSSI);
+        dest.writeInt(numTicksAtNotHighRSSI);
+        dest.writeInt(numUserTriggeredJoinAttempts);
+
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -1307,6 +1401,7 @@
                 config.autoJoinStatus = in.readInt();
                 config.selfAdded = in.readInt() != 0;
                 config.didSelfAdd = in.readInt() != 0;
+                config.noInternetAccess = in.readInt() != 0;
                 config.creatorUid = in.readInt();
                 config.lastConnectUid = in.readInt();
                 config.lastUpdateUid = in.readInt();
@@ -1317,6 +1412,13 @@
                 config.numScorerOverride = in.readInt();
                 config.numScorerOverrideAndSwitchedNetwork = in.readInt();
                 config.numAssociation = in.readInt();
+                config.numUserTriggeredWifiDisableLowRSSI = in.readInt();
+                config.numUserTriggeredWifiDisableBadRSSI = in.readInt();
+                config.numUserTriggeredWifiDisableNotHighRSSI = in.readInt();
+                config.numTicksAtLowRSSI = in.readInt();
+                config.numTicksAtBadRSSI = in.readInt();
+                config.numTicksAtNotHighRSSI = in.readInt();
+                config.numUserTriggeredJoinAttempts = in.readInt();
                 return config;
             }