Merge "MediaPlayer2: fix a regression from I5d4884353057a195b1f587694"
diff --git a/api/current.txt b/api/current.txt
index e31f8a0..b9e00f6 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -42654,6 +42654,7 @@
     method public static int[] getSubscriptionIds(int);
     method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
     method public boolean isNetworkRoaming(int);
+    method public static boolean isValidSubscriptionId(int);
     method public void removeOnOpportunisticSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
     method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
     method public void setSubscriptionOverrideCongested(int, boolean, long);
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 3fae586..94203f4f 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -46,6 +46,7 @@
 // ====  java proto device library (for test only)  ==============================
 java_library {
     name: "statsdprotolite",
+    no_framework_libs: true,
     proto: {
         type: "lite",
         include_dirs: ["external/protobuf/src"],
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 8f3ad9d..d117f39 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -30,6 +30,7 @@
 import "frameworks/base/core/proto/android/telephony/enums.proto";
 import "frameworks/base/core/proto/android/view/enums.proto";
 import "frameworks/base/proto/src/stats_enums.proto";
+import "frameworks/base/core/proto/android/service/procstats.proto";
 
 /**
  * The master atom class. This message defines all of the available
@@ -165,6 +166,7 @@
         DirectoryUsage directory_usage = 10026;
         AppSize app_size = 10027;
         CategorySize category_size = 10028;
+        android.service.procstats.ProcessStatsSectionProto proc_stats = 10029;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP. Field numbers above
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index f07f5ec..d3b2238 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -20,13 +20,14 @@
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
-import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
+
 import com.android.internal.annotations.GuardedBy;
 
 import java.util.Set;
@@ -45,6 +46,7 @@
 
     public final String name;
     public final String type;
+    private String mSafeName;
     @UnsupportedAppUsage
     private final @Nullable String accessId;
 
@@ -135,4 +137,37 @@
     public String toString() {
         return "Account {name=" + name + ", type=" + type + "}";
     }
+
+    /**
+     * Return a string representation of the account that is safe to print
+     * to logs and other places where PII should be avoided.
+     * @hide
+     */
+    public String toSafeString() {
+        if (mSafeName == null) {
+            mSafeName = toSafeName(name, 'x');
+        }
+        return "Account {name=" + mSafeName + ", type=" + type + "}";
+    }
+
+    /**
+     * Given a name, replace all letter or digits with the replacement char.
+     * @param name The input name string.
+     * @param replacement the replacement character.
+     * @return the string after replacement.
+     * @hide
+     */
+    public static String toSafeName(String name, char replacement) {
+        final StringBuilder builder = new StringBuilder(64);
+        final int len = name.length();
+        for (int i = 0; i < len; i++) {
+            final char c = name.charAt(i);
+            if (Character.isLetterOrDigit(c)) {
+                builder.append(replacement);
+            } else {
+                builder.append(c);
+            }
+        }
+        return builder.toString();
+    }
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 041a5b0..bf2d860 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1461,7 +1461,7 @@
      */
     @Override
     public AutofillId autofillClientGetNextAutofillId() {
-        return new AutofillId(getAutofillManager(), getNextAutofillId());
+        return new AutofillId(getNextAutofillId());
     }
 
     /**
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index ee6a81d..173b766 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -32,7 +32,6 @@
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
 
 import com.android.internal.util.Preconditions;
@@ -73,8 +72,6 @@
     boolean mHaveData;
 
     ComponentName mActivityComponent;
-    // Not written to parcel, only used to set session id on virtual node children
-    private final int mAutofillSessionId;
     private boolean mIsHomeActivity;
     private int mFlags;
 
@@ -1849,13 +1846,11 @@
         @Override
         public void setAutofillId(@NonNull AutofillId id) {
             mNode.mAutofillId = id;
-            mNode.mAutofillId.setSessionId(mAssist.mAutofillSessionId);
         }
 
         @Override
         public void setAutofillId(@NonNull AutofillId parentId, int virtualId) {
             mNode.mAutofillId = new AutofillId(parentId, virtualId);
-            mNode.mAutofillId.setSessionId(mAssist.mAutofillSessionId);
         }
 
         @Override
@@ -2045,8 +2040,6 @@
     public AssistStructure(Activity activity, boolean forAutoFill, int flags) {
         mHaveData = true;
         mActivityComponent = activity.getComponentName();
-        final AutofillManager afm = activity.getSystemService(AutofillManager.class);
-        mAutofillSessionId = afm == null ? AutofillManager.NO_SESSION : afm.getSessionId();
         mFlags = flags;
         ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
                 activity.getActivityToken());
@@ -2063,7 +2056,6 @@
     public AssistStructure() {
         mHaveData = true;
         mActivityComponent = null;
-        mAutofillSessionId = AutofillManager.NO_SESSION;
         mFlags = 0;
     }
 
@@ -2071,7 +2063,6 @@
     public AssistStructure(Parcel in) {
         mIsHomeActivity = in.readInt() == 1;
         mReceiveChannel = in.readStrongBinder();
-        mAutofillSessionId = AutofillManager.NO_SESSION;
     }
 
     /**
@@ -2091,10 +2082,6 @@
             ensureData();
         }
         Log.i(TAG, "Activity: " + mActivityComponent.flattenToShortString());
-        if (mAutofillSessionId != AutofillManager.NO_SESSION) {
-            Log.i(TAG, "Autofill Session ID: " + mAutofillSessionId);
-        }
-
         Log.i(TAG, "Sanitize on write: " + mSanitizeOnWrite);
         Log.i(TAG, "Flags: " + mFlags);
         final int N = getWindowNodeCount();
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index d9d1777..9e20503 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -234,7 +234,7 @@
     /**
      * Array of all signatures read from the package file. This is only filled
      * in if the flag {@link PackageManager#GET_SIGNATURES} was set. A package
-     * must be singed with at least one certificate which is at position zero.
+     * must be signed with at least one certificate which is at position zero.
      * The package can be signed with additional certificates which appear as
      * subsequent entries.
      *
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 1ee3c93..cb33659 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -58,7 +58,7 @@
  * execute in parallel with any {@link Surface} initialization, such as waiting for a
  * {@link android.view.SurfaceView} to be ready as part of the UI initialization.</li>
  *
- * <li>The third and most complex usage pattern inlvolves surface sharing. Once instantiated an
+ * <li>The third and most complex usage pattern involves surface sharing. Once instantiated an
  * OutputConfiguration can be enabled for surface sharing via {@link #enableSurfaceSharing}. This
  * must be done before creating a new capture session and enables calls to
  * {@link CameraCaptureSession#updateOutputConfiguration}. An OutputConfiguration with enabled
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 6d9ba77..7e52ca3 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -141,13 +141,6 @@
         private String mDescription;
 
         /**
-         * STOPSHIP remove when app has stopped using this.
-         * @hide
-         */
-        public Builder() {
-        }
-
-        /**
          * Constructs the builder with the control points for the brightness curve.
          *
          * Brightness curves must have strictly increasing ambient brightness values in lux and
@@ -159,24 +152,6 @@
          * @throws IllegalArgumentException if the nit levels are not monotonically increasing.
          */
         public Builder(float[] lux, float[] nits) {
-            setCurve(lux, nits);
-        }
-
-        /**
-         * Sets the control points for the brightness curve.
-         *
-         * Brightness curves must have strictly increasing ambient brightness values in lux and
-         * monotonically increasing display brightness values in nits. In addition, the initial
-         * control point must be 0 lux.
-         *
-         * @throws IllegalArgumentException if the initial control point is not at 0 lux.
-         * @throws IllegalArgumentException if the lux levels are not strictly increasing.
-         * @throws IllegalArgumentException if the nit levels are not monotonically increasing.
-         *
-         * STOPSHIP remove when app has stopped using this.
-         * @hide
-         */
-        public Builder setCurve(float[] lux, float[] nits) {
             Preconditions.checkNotNull(lux);
             Preconditions.checkNotNull(nits);
             if (lux.length == 0 || nits.length == 0) {
@@ -190,11 +165,10 @@
             }
             Preconditions.checkArrayElementsInRange(lux, 0, Float.MAX_VALUE, "lux");
             Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits");
-            checkMonotonic(lux, true/*strictly increasing*/, "lux");
+            checkMonotonic(lux, true /*strictly increasing*/, "lux");
             checkMonotonic(nits, false /*strictly increasing*/, "nits");
             mCurveLux = lux;
             mCurveNits = nits;
-            return this;
         }
 
         /**
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
index 185215a..b0fca00 100644
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java
@@ -252,4 +252,12 @@
         return;
     }
 
+    /**
+     * Called when the user took some actions that should be taken into consideration to update the
+     * MRU list for input method rotation.
+     *
+     * @hide
+     */
+    public void notifyUserActionIfNecessary() {
+    }
 }
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 00a1f6f..4080ee6 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -87,8 +87,8 @@
      * guarantees that {@link #bindInput(InputBinding)},
      * {@link #startInput(IBinder, IInputContext, int, EditorInfo, boolean)}, and
      * {@link #unbindInput()} are called with the same order as the original calls
-     * in {@link com.android.server.InputMethodManagerService}.  See {@link IBinder#FLAG_ONEWAY}
-     * for detailed semantics.</p>
+     * in {@link com.android.server.inputmethod.InputMethodManagerService}.
+     * See {@link IBinder#FLAG_ONEWAY} for detailed semantics.</p>
      */
     AtomicBoolean mIsUnbindIssued = null;
 
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index aa5cf09..2d12b86 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -22,6 +22,7 @@
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
+import android.annotation.AnyThread;
 import android.annotation.CallSuper;
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
@@ -79,6 +80,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.inputmethod.IInputContentUriToken;
 import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
 import com.android.internal.inputmethod.InputMethodPrivilegedOperations;
@@ -402,6 +404,10 @@
     @BackDispositionMode
     int mBackDisposition;
 
+    private Object mLock = new Object();
+    @GuardedBy("mLock")
+    private boolean mNotifyUserActionSent;
+
     /**
      * {@code true} when the previous IME had non-empty inset at the bottom of the screen and we
      * have not shown our own window yet.  In this situation, the previous inset continues to be
@@ -594,7 +600,7 @@
         @MainThread
         @Override
         public void changeInputMethodSubtype(InputMethodSubtype subtype) {
-            onCurrentInputMethodSubtypeChanged(subtype);
+            dispatchOnCurrentInputMethodSubtypeChanged(subtype);
         }
     }
 
@@ -2792,6 +2798,13 @@
         }
     }
 
+    private void dispatchOnCurrentInputMethodSubtypeChanged(InputMethodSubtype newSubtype) {
+        synchronized (mLock) {
+            mNotifyUserActionSent = false;
+        }
+        onCurrentInputMethodSubtypeChanged(newSubtype);
+    }
+
     // TODO: Handle the subtype change event
     /**
      * Called when the subtype was changed.
@@ -2848,6 +2861,22 @@
     }
 
     /**
+     * {@inheritDoc}
+     * @hide
+     */
+    @AnyThread
+    @Override
+    public final void notifyUserActionIfNecessary() {
+        synchronized (mLock) {
+            if (mNotifyUserActionSent) {
+                return;
+            }
+            mPrivOps.notifyUserActionAsync();
+            mNotifyUserActionSent = true;
+        }
+    }
+
+    /**
      * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
      * permission to the content.
      *
diff --git a/core/java/android/service/autofill/CharSequenceTransformation.java b/core/java/android/service/autofill/CharSequenceTransformation.java
index fa6bd65..271707a 100644
--- a/core/java/android/service/autofill/CharSequenceTransformation.java
+++ b/core/java/android/service/autofill/CharSequenceTransformation.java
@@ -90,7 +90,7 @@
             try {
                 final Matcher matcher = field.first.matcher(value);
                 if (!matcher.find()) {
-                    if (sDebug) Log.d(TAG, "match for " + field.first + " failed on id " + id);
+                    if (sDebug) Log.d(TAG, "Match for " + field.first + " failed on id " + id);
                     return;
                 }
                 // replaceAll throws an exception if the subst is invalid
@@ -103,6 +103,9 @@
                 throw e;
             }
         }
+        // Cannot log converted, it might have PII
+        Log.d(TAG, "Converting text on child " + childViewId + " to " + converted.length()
+                + "_chars");
         parentTemplate.setCharSequence(childViewId, "setText", converted);
     }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4a61906..9bc53ed 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8251,7 +8251,7 @@
         if (mAutofillId == null) {
             // The autofill id needs to be unique, but its value doesn't matter,
             // so it's better to reuse the accessibility id to save space.
-            mAutofillId = new AutofillId(getAutofillManager(), getAutofillViewId());
+            mAutofillId = new AutofillId(getAutofillViewId());
         }
         return mAutofillId;
     }
@@ -8313,15 +8313,11 @@
             // Ignore reset because it was never explicitly set before.
             return;
         }
+        mAutofillId = id;
         if (id != null) {
-            // Must create a new id so the session id is preserved.
-            final int oldSessionId = mAutofillId.getSessionId();
             mAutofillViewId = id.getViewId();
-            mAutofillId = new AutofillId(mAutofillViewId);
-            mAutofillId.setSessionId(oldSessionId);
             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
         } else {
-            mAutofillId = null;
             mAutofillViewId = NO_ID;
             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
         }
@@ -8611,11 +8607,8 @@
             structure.setContextClickable(true);
         }
         if (forAutofill) {
-            final AutofillId autofillId = new AutofillId(getAutofillId(),
-                    AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()));
-            final AutofillManager afm = getAutofillManager();
-            autofillId.setSessionId(afm == null ? AutofillManager.NO_SESSION : afm.getSessionId());
-            structure.setAutofillId(autofillId);
+            structure.setAutofillId(new AutofillId(getAutofillId(),
+                    AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
         }
         CharSequence cname = info.getClassName();
         structure.setClassName(cname != null ? cname.toString() : null);
diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java
index 5ae91a5..cb1d89c 100644
--- a/core/java/android/view/autofill/AutofillId.java
+++ b/core/java/android/view/autofill/AutofillId.java
@@ -15,10 +15,6 @@
  */
 package android.view.autofill;
 
-import static android.view.autofill.Helper.sDebug;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -32,7 +28,6 @@
     private final int mViewId;
     private final boolean mVirtual;
     private final int mVirtualId;
-    private int mSessionId = AutofillManager.NO_SESSION;
 
     /** @hide */
     @TestApi
@@ -43,26 +38,18 @@
     }
 
     /** @hide */
-    // NOTE: caller must set sessionId
     @TestApi
-    public AutofillId(@NonNull AutofillId parent, int virtualChildId) {
+    public AutofillId(AutofillId parent, int virtualChildId) {
         mVirtual = true;
         mViewId = parent.mViewId;
         mVirtualId = virtualChildId;
     }
 
     /** @hide */
-    public AutofillId(int sessionId, int parentId, int virtualChildId) {
+    public AutofillId(int parentId, int virtualChildId) {
         mVirtual = true;
         mViewId = parentId;
         mVirtualId = virtualChildId;
-        mSessionId = sessionId;
-    }
-
-    /** @hide */
-    public AutofillId(@Nullable AutofillManager afm, int id) {
-        this(id);
-        mSessionId = afm == null ? AutofillManager.NO_SESSION : afm.getSessionId();
     }
 
     /** @hide */
@@ -80,16 +67,6 @@
         return mVirtual;
     }
 
-    /** @hide */
-    public int getSessionId() {
-        return mSessionId;
-    }
-
-    /** @hide */
-    public void setSessionId(int sessionId) {
-        this.mSessionId = sessionId;
-    }
-
     /////////////////////////////////
     //  Object "contract" methods. //
     /////////////////////////////////
@@ -100,7 +77,6 @@
         int result = 1;
         result = prime * result + mViewId;
         result = prime * result + mVirtualId;
-        result = prime * result + mSessionId;
         return result;
     }
 
@@ -112,7 +88,6 @@
         final AutofillId other = (AutofillId) obj;
         if (mViewId != other.mViewId) return false;
         if (mVirtualId != other.mVirtualId) return false;
-        if (mSessionId != other.mSessionId) return false;
         return true;
     }
 
@@ -122,9 +97,6 @@
         if (mVirtual) {
             builder.append(':').append(mVirtualId);
         }
-        if (mSessionId != AutofillManager.NO_SESSION && sDebug) {
-            builder.append('<').append(mSessionId).append('>');
-        }
         return builder.toString();
     }
 
@@ -138,14 +110,12 @@
         parcel.writeInt(mViewId);
         parcel.writeInt(mVirtual ? 1 : 0);
         parcel.writeInt(mVirtualId);
-        parcel.writeInt(mSessionId);
     }
 
     private AutofillId(Parcel parcel) {
         mViewId = parcel.readInt();
         mVirtual = parcel.readInt() == 1;
         mVirtualId = parcel.readInt();
-        mSessionId = parcel.readInt();
     }
 
     public static final Parcelable.Creator<AutofillId> CREATOR =
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 612888e..9419e93 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -916,7 +916,7 @@
             boolean isVisible, boolean virtual) {
         synchronized (mLock) {
             if (mEnabled && isActiveLocked()) {
-                final AutofillId id = virtual ? getAutofillIdLocked(view, virtualId)
+                final AutofillId id = virtual ? getAutofillId(view, virtualId)
                         : view.getAutofillId();
                 if (sVerbose) Log.v(TAG, "visibility changed for " + id + ": " + isVisible);
                 if (!isVisible && mFillableIds != null) {
@@ -976,7 +976,7 @@
     @GuardedBy("mLock")
     private AutofillCallback notifyViewEnteredLocked(View view, int virtualId, Rect bounds,
                                                      int flags) {
-        final AutofillId id = getAutofillIdLocked(view, virtualId);
+        final AutofillId id = getAutofillId(view, virtualId);
         AutofillCallback callback = null;
         if (shouldIgnoreViewEnteredLocked(id, flags)) return callback;
 
@@ -1033,7 +1033,7 @@
         if (mEnabled && isActiveLocked()) {
             // don't notify exited when Activity is already in background
             if (!isClientDisablingEnterExitEvent()) {
-                final AutofillId id = getAutofillIdLocked(view, virtualId);
+                final AutofillId id = getAutofillId(view, virtualId);
 
                 // Update focus on existing session.
                 updateSessionLocked(id, null, null, ACTION_VIEW_EXITED, 0);
@@ -1116,7 +1116,7 @@
                 return;
             }
 
-            final AutofillId id = getAutofillIdLocked(view, virtualId);
+            final AutofillId id = getAutofillId(view, virtualId);
             updateSessionLocked(id, null, value, ACTION_VALUE_CHANGED, 0);
         }
     }
@@ -1137,11 +1137,7 @@
      * @param virtualId id identifying the virtual child inside the parent view.
      */
     public void notifyViewClicked(@NonNull View view, int virtualId) {
-        final AutofillId id;
-        synchronized (mLock) {
-            id = getAutofillIdLocked(view, virtualId);
-        }
-        notifyViewClicked(id);
+        notifyViewClicked(getAutofillId(view, virtualId));
     }
 
     private void notifyViewClicked(AutofillId id) {
@@ -1538,9 +1534,8 @@
         return id;
     }
 
-    @GuardedBy("mLock")
-    private AutofillId getAutofillIdLocked(View parent, int virtualId) {
-        return new AutofillId(mSessionId, parent.getAutofillViewId(), virtualId);
+    private static AutofillId getAutofillId(View parent, int virtualId) {
+        return new AutofillId(parent.getAutofillViewId(), virtualId);
     }
 
     @GuardedBy("mLock")
@@ -1571,8 +1566,6 @@
             mSessionId = receiver.getIntResult();
             if (mSessionId != NO_SESSION) {
                 mState = STATE_ACTIVE;
-                // Need to update the view's autofill id with the session
-                id.setSessionId(mSessionId);
             }
             client.autofillClientResetableStateAvailable();
         } catch (RemoteException e) {
@@ -2217,13 +2210,6 @@
         return getStateAsString(mState);
     }
 
-    /** @hide */
-    public int getSessionId() {
-        synchronized (mLock) {
-            return mSessionId;
-        }
-    }
-
     @NonNull
     private static String getStateAsString(int state) {
         switch (state) {
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 89d9ada..c51c5e2 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -30,6 +30,7 @@
 import android.content.pm.PackageManager;
 import android.graphics.Rect;
 import android.inputmethodservice.InputMethodService;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -353,28 +354,6 @@
     int mCursorCandEnd;
 
     /**
-     * Represents an invalid action notification sequence number.
-     * {@link com.android.server.InputMethodManagerService} always issues a positive integer for
-     * action notification sequence numbers. Thus {@code -1} is guaranteed to be different from any
-     * valid sequence number.
-     */
-    private static final int NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER = -1;
-    /**
-     * The next sequence number that is to be sent to
-     * {@link com.android.server.InputMethodManagerService} via
-     * {@link IInputMethodManager#notifyUserAction(int)} at once when a user action is observed.
-     */
-    private int mNextUserActionNotificationSequenceNumber =
-            NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER;
-
-    /**
-     * The last sequence number that is already sent to
-     * {@link com.android.server.InputMethodManagerService}.
-     */
-    private int mLastSentUserActionNotificationSequenceNumber =
-            NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER;
-
-    /**
      * The instance that has previously been sent to the input method.
      */
     private CursorAnchorInfo mCursorAnchorInfo = null;
@@ -420,7 +399,6 @@
     static final int MSG_SEND_INPUT_EVENT = 5;
     static final int MSG_TIMEOUT_INPUT_EVENT = 6;
     static final int MSG_FLUSH_INPUT_EVENT = 7;
-    static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 9;
     static final int MSG_REPORT_FULLSCREEN_MODE = 10;
 
     private static boolean isAutofillUIShowing(View servedView) {
@@ -557,12 +535,6 @@
                     finishedInputEvent(msg.arg1, false, false);
                     return;
                 }
-                case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: {
-                    synchronized (mH) {
-                        mNextUserActionNotificationSequenceNumber = msg.arg1;
-                    }
-                    return;
-                }
                 case MSG_REPORT_FULLSCREEN_MODE: {
                     final boolean fullscreen = msg.arg1 != 0;
                     InputConnection ic = null;
@@ -605,11 +577,6 @@
         }
 
         @Override
-        protected void onUserAction() {
-            mParentInputMethodManager.notifyUserAction();
-        }
-
-        @Override
         public String toString() {
             return "ControlledInputConnectionWrapper{"
                     + "connection=" + getInputConnection()
@@ -656,12 +623,6 @@
         }
 
         @Override
-        public void setUserActionNotificationSequenceNumber(int sequenceNumber) {
-            mH.obtainMessage(MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER, sequenceNumber, 0)
-                    .sendToTarget();
-        }
-
-        @Override
         public void reportFullscreenMode(boolean fullscreen) {
             mH.obtainMessage(MSG_REPORT_FULLSCREEN_MODE, fullscreen ? 1 : 0, 0)
                     .sendToTarget();
@@ -1354,8 +1315,6 @@
                     mBindSequence = res.sequence;
                     mCurMethod = res.method;
                     mCurId = res.id;
-                    mNextUserActionNotificationSequenceNumber =
-                            res.userActionNotificationSequenceNumber;
                 } else if (res.channel != null && res.channel != mCurChannel) {
                     res.channel.dispose();
                 }
@@ -2189,37 +2148,16 @@
 
     /**
      * Notify that a user took some action with this input method.
+     *
+     * @deprecated Just kept to avoid possible app compat issue.
      * @hide
      */
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(trackingBug = 114740982, maxTargetSdk = Build.VERSION_CODES.P)
     public void notifyUserAction() {
-        synchronized (mH) {
-            if (mLastSentUserActionNotificationSequenceNumber ==
-                    mNextUserActionNotificationSequenceNumber) {
-                if (DEBUG) {
-                    Log.w(TAG, "Ignoring notifyUserAction as it has already been sent."
-                            + " mLastSentUserActionNotificationSequenceNumber: "
-                            + mLastSentUserActionNotificationSequenceNumber
-                            + " mNextUserActionNotificationSequenceNumber: "
-                            + mNextUserActionNotificationSequenceNumber);
-                }
-                return;
-            }
-            try {
-                if (DEBUG) {
-                    Log.w(TAG, "notifyUserAction: "
-                            + " mLastSentUserActionNotificationSequenceNumber: "
-                            + mLastSentUserActionNotificationSequenceNumber
-                            + " mNextUserActionNotificationSequenceNumber: "
-                            + mNextUserActionNotificationSequenceNumber);
-                }
-                mService.notifyUserAction(mNextUserActionNotificationSequenceNumber);
-                mLastSentUserActionNotificationSequenceNumber =
-                        mNextUserActionNotificationSequenceNumber;
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
+        Log.w(TAG, "notifyUserAction() is a hidden method, which is now just a stub method"
+                + " that does nothing.  Leave comments in b.android.com/114740982 if your "
+                + " application still depends on the previous behavior of this method.");
     }
 
     /**
@@ -2420,10 +2358,6 @@
                 + " mCursorSelEnd=" + mCursorSelEnd
                 + " mCursorCandStart=" + mCursorCandStart
                 + " mCursorCandEnd=" + mCursorCandEnd);
-        p.println("  mNextUserActionNotificationSequenceNumber="
-                + mNextUserActionNotificationSequenceNumber
-                + " mLastSentUserActionNotificationSequenceNumber="
-                + mLastSentUserActionNotificationSequenceNumber);
     }
 
     /**
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index a7d7a8d..61a6972 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -28,7 +28,7 @@
 import android.text.TextUtils;
 import android.util.Slog;
 
-import com.android.internal.inputmethod.InputMethodUtils;
+import com.android.internal.inputmethod.LocaleUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -384,7 +384,7 @@
             if (!TextUtils.isEmpty(mSubtypeLanguageTag)) {
                 mCachedLocaleObj = Locale.forLanguageTag(mSubtypeLanguageTag);
             } else {
-                mCachedLocaleObj = InputMethodUtils.constructLocaleFromString(mSubtypeLocale);
+                mCachedLocaleObj = LocaleUtils.constructLocaleFromString(mSubtypeLocale);
             }
             return mCachedLocaleObj;
         }
diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java
index 026610e..41b70b6 100644
--- a/core/java/android/view/textservice/SpellCheckerSubtype.java
+++ b/core/java/android/view/textservice/SpellCheckerSubtype.java
@@ -25,7 +25,7 @@
 import android.text.TextUtils;
 import android.util.Slog;
 
-import com.android.internal.inputmethod.InputMethodUtils;
+import com.android.internal.inputmethod.LocaleUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -228,7 +228,7 @@
         if (!TextUtils.isEmpty(mSubtypeLanguageTag)) {
             return Locale.forLanguageTag(mSubtypeLanguageTag);
         }
-        return InputMethodUtils.constructLocaleFromString(mSubtypeLocale);
+        return LocaleUtils.constructLocaleFromString(mSubtypeLocale);
     }
 
     /**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 0645a16..d913273 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -313,6 +313,7 @@
  * @attr ref android.R.styleable#TextView_fallbackLineSpacing
  * @attr ref android.R.styleable#TextView_letterSpacing
  * @attr ref android.R.styleable#TextView_fontFeatureSettings
+ * @attr ref android.R.styleable#TextView_fontVariationSettings
  * @attr ref android.R.styleable#TextView_breakStrategy
  * @attr ref android.R.styleable#TextView_hyphenationFrequency
  * @attr ref android.R.styleable#TextView_autoSizeTextType
@@ -4382,6 +4383,8 @@
      *
      * @see #getFontVariationSettings()
      * @see FontVariationAxis
+     *
+     * @attr ref android.R.styleable#TextView_fontVariationSettings
      */
     public boolean setFontVariationSettings(@Nullable String fontVariationSettings) {
         final String existingSettings = mTextPaint.getFontVariationSettings();
diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
index e998a52..c32894d 100644
--- a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
@@ -39,4 +39,6 @@
     boolean switchToPreviousInputMethod();
     boolean switchToNextInputMethod(boolean onlyCurrentIme);
     boolean shouldOfferSwitchingToNextInputMethod();
+
+    oneway void notifyUserActionAsync();
 }
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
index 7891540..f0e8dc5 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
@@ -346,4 +346,20 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#notifyUserActionAsync()}
+     */
+    @AnyThread
+    public void notifyUserActionAsync() {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.notifyUserActionAsync();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 1e5b5c8..1410ff9 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -334,32 +334,6 @@
         return getDefaultEnabledImes(context, imis, false /* onlyMinimum */);
     }
 
-    public static Locale constructLocaleFromString(String localeStr) {
-        if (TextUtils.isEmpty(localeStr)) {
-            return null;
-        }
-        // TODO: Use {@link Locale#toLanguageTag()} and {@link Locale#forLanguageTag(languageTag)}.
-        String[] localeParams = localeStr.split("_", 3);
-        if (localeParams.length >= 1 && "tl".equals(localeParams[0])) {
-             // Convert a locale whose language is "tl" to one whose language is "fil".
-             // For example, "tl_PH" will get converted to "fil_PH".
-             // Versions of Android earlier than Lollipop did not support three letter language
-             // codes, and used "tl" (Tagalog) as the language string for "fil" (Filipino).
-             // On Lollipop and above, the current three letter version must be used.
-             localeParams[0] = "fil";
-        }
-        // The length of localeStr is guaranteed to always return a 1 <= value <= 3
-        // because localeStr is not empty.
-        if (localeParams.length == 1) {
-            return new Locale(localeParams[0]);
-        } else if (localeParams.length == 2) {
-            return new Locale(localeParams[0], localeParams[1]);
-        } else if (localeParams.length == 3) {
-            return new Locale(localeParams[0], localeParams[1], localeParams[2]);
-        }
-        return null;
-    }
-
     public static boolean containsSubtypeOf(final InputMethodInfo imi,
             @Nullable final Locale locale, final boolean checkCountry, final String mode) {
         if (locale == null) {
@@ -1320,133 +1294,7 @@
         }
     }
 
-    // For spell checker service manager.
-    // TODO: Should we have TextServicesUtils.java?
-    private static final Locale LOCALE_EN_US = new Locale("en", "US");
-    private static final Locale LOCALE_EN_GB = new Locale("en", "GB");
-
-    /**
-     * Returns a list of {@link Locale} in the order of appropriateness for the default spell
-     * checker service.
-     *
-     * <p>If the system language is English, and the region is also explicitly specified in the
-     * system locale, the following fallback order will be applied.</p>
-     * <ul>
-     * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li>
-     * <li>(system-locale-language, system-locale-region)</li>
-     * <li>("en", "US")</li>
-     * <li>("en", "GB")</li>
-     * <li>("en")</li>
-     * </ul>
-     *
-     * <p>If the system language is English, but no region is specified in the system locale,
-     * the following fallback order will be applied.</p>
-     * <ul>
-     * <li>("en")</li>
-     * <li>("en", "US")</li>
-     * <li>("en", "GB")</li>
-     * </ul>
-     *
-     * <p>If the system language is not English, the following fallback order will be applied.</p>
-     * <ul>
-     * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li>
-     * <li>(system-locale-language, system-locale-region) (if exists)</li>
-     * <li>(system-locale-language) (if exists)</li>
-     * <li>("en", "US")</li>
-     * <li>("en", "GB")</li>
-     * <li>("en")</li>
-     * </ul>
-     *
-     * @param systemLocale the current system locale to be taken into consideration.
-     * @return a list of {@link Locale}. The first one is considered to be most appropriate.
-     */
     @VisibleForTesting
-    public static ArrayList<Locale> getSuitableLocalesForSpellChecker(
-            @Nullable final Locale systemLocale) {
-        final Locale systemLocaleLanguageCountryVariant;
-        final Locale systemLocaleLanguageCountry;
-        final Locale systemLocaleLanguage;
-        if (systemLocale != null) {
-            final String language = systemLocale.getLanguage();
-            final boolean hasLanguage = !TextUtils.isEmpty(language);
-            final String country = systemLocale.getCountry();
-            final boolean hasCountry = !TextUtils.isEmpty(country);
-            final String variant = systemLocale.getVariant();
-            final boolean hasVariant = !TextUtils.isEmpty(variant);
-            if (hasLanguage && hasCountry && hasVariant) {
-                systemLocaleLanguageCountryVariant = new Locale(language, country, variant);
-            } else {
-                systemLocaleLanguageCountryVariant = null;
-            }
-            if (hasLanguage && hasCountry) {
-                systemLocaleLanguageCountry = new Locale(language, country);
-            } else {
-                systemLocaleLanguageCountry = null;
-            }
-            if (hasLanguage) {
-                systemLocaleLanguage = new Locale(language);
-            } else {
-                systemLocaleLanguage = null;
-            }
-        } else {
-            systemLocaleLanguageCountryVariant = null;
-            systemLocaleLanguageCountry = null;
-            systemLocaleLanguage = null;
-        }
-
-        final ArrayList<Locale> locales = new ArrayList<>();
-        if (systemLocaleLanguageCountryVariant != null) {
-            locales.add(systemLocaleLanguageCountryVariant);
-        }
-
-        if (Locale.ENGLISH.equals(systemLocaleLanguage)) {
-            if (systemLocaleLanguageCountry != null) {
-                // If the system language is English, and the region is also explicitly specified,
-                // following fallback order will be applied.
-                // - systemLocaleLanguageCountry [if systemLocaleLanguageCountry is non-null]
-                // - en_US [if systemLocaleLanguageCountry is non-null and not en_US]
-                // - en_GB [if systemLocaleLanguageCountry is non-null and not en_GB]
-                // - en
-                if (systemLocaleLanguageCountry != null) {
-                    locales.add(systemLocaleLanguageCountry);
-                }
-                if (!LOCALE_EN_US.equals(systemLocaleLanguageCountry)) {
-                    locales.add(LOCALE_EN_US);
-                }
-                if (!LOCALE_EN_GB.equals(systemLocaleLanguageCountry)) {
-                    locales.add(LOCALE_EN_GB);
-                }
-                locales.add(Locale.ENGLISH);
-            } else {
-                // If the system language is English, but no region is specified, following
-                // fallback order will be applied.
-                // - en
-                // - en_US
-                // - en_GB
-                locales.add(Locale.ENGLISH);
-                locales.add(LOCALE_EN_US);
-                locales.add(LOCALE_EN_GB);
-            }
-        } else {
-            // If the system language is not English, the fallback order will be
-            // - systemLocaleLanguageCountry  [if non-null]
-            // - systemLocaleLanguage  [if non-null]
-            // - en_US
-            // - en_GB
-            // - en
-            if (systemLocaleLanguageCountry != null) {
-                locales.add(systemLocaleLanguageCountry);
-            }
-            if (systemLocaleLanguage != null) {
-                locales.add(systemLocaleLanguage);
-            }
-            locales.add(LOCALE_EN_US);
-            locales.add(LOCALE_EN_GB);
-            locales.add(Locale.ENGLISH);
-        }
-        return locales;
-    }
-
     public static boolean isSoftInputModeStateVisibleAllowed(
             int targetSdkVersion, int controlFlags) {
         if (targetSdkVersion < Build.VERSION_CODES.P) {
@@ -1461,5 +1309,4 @@
         }
         return true;
     }
-
 }
diff --git a/core/java/com/android/internal/inputmethod/LocaleUtils.java b/core/java/com/android/internal/inputmethod/LocaleUtils.java
index eeb3854..f7360eb 100644
--- a/core/java/com/android/internal/inputmethod/LocaleUtils.java
+++ b/core/java/com/android/internal/inputmethod/LocaleUtils.java
@@ -16,8 +16,6 @@
 
 package com.android.internal.inputmethod;
 
-import com.android.internal.annotations.VisibleForTesting;
-
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -25,6 +23,8 @@
 import android.os.LocaleList;
 import android.text.TextUtils;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -208,4 +208,151 @@
             dest.add(sources.get(entry.mIndex));
         }
     }
+
+    public static Locale constructLocaleFromString(String localeStr) {
+        if (TextUtils.isEmpty(localeStr)) {
+            return null;
+        }
+        // TODO: Use {@link Locale#toLanguageTag()} and {@link Locale#forLanguageTag(languageTag)}.
+        String[] localeParams = localeStr.split("_", 3);
+        if (localeParams.length >= 1 && "tl".equals(localeParams[0])) {
+            // Convert a locale whose language is "tl" to one whose language is "fil".
+            // For example, "tl_PH" will get converted to "fil_PH".
+            // Versions of Android earlier than Lollipop did not support three letter language
+            // codes, and used "tl" (Tagalog) as the language string for "fil" (Filipino).
+            // On Lollipop and above, the current three letter version must be used.
+            localeParams[0] = "fil";
+        }
+        // The length of localeStr is guaranteed to always return a 1 <= value <= 3
+        // because localeStr is not empty.
+        if (localeParams.length == 1) {
+            return new Locale(localeParams[0]);
+        } else if (localeParams.length == 2) {
+            return new Locale(localeParams[0], localeParams[1]);
+        } else if (localeParams.length == 3) {
+            return new Locale(localeParams[0], localeParams[1], localeParams[2]);
+        }
+        return null;
+    }
+
+    /**
+     * Returns a list of {@link Locale} in the order of appropriateness for the default spell
+     * checker service.
+     *
+     * <p>If the system language is English, and the region is also explicitly specified in the
+     * system locale, the following fallback order will be applied.</p>
+     * <ul>
+     * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li>
+     * <li>(system-locale-language, system-locale-region)</li>
+     * <li>("en", "US")</li>
+     * <li>("en", "GB")</li>
+     * <li>("en")</li>
+     * </ul>
+     *
+     * <p>If the system language is English, but no region is specified in the system locale,
+     * the following fallback order will be applied.</p>
+     * <ul>
+     * <li>("en")</li>
+     * <li>("en", "US")</li>
+     * <li>("en", "GB")</li>
+     * </ul>
+     *
+     * <p>If the system language is not English, the following fallback order will be applied.</p>
+     * <ul>
+     * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li>
+     * <li>(system-locale-language, system-locale-region) (if exists)</li>
+     * <li>(system-locale-language) (if exists)</li>
+     * <li>("en", "US")</li>
+     * <li>("en", "GB")</li>
+     * <li>("en")</li>
+     * </ul>
+     *
+     * @param systemLocale the current system locale to be taken into consideration.
+     * @return a list of {@link Locale}. The first one is considered to be most appropriate.
+     */
+    public static ArrayList<Locale> getSuitableLocalesForSpellChecker(
+            @Nullable final Locale systemLocale) {
+        final Locale systemLocaleLanguageCountryVariant;
+        final Locale systemLocaleLanguageCountry;
+        final Locale systemLocaleLanguage;
+        if (systemLocale != null) {
+            final String language = systemLocale.getLanguage();
+            final boolean hasLanguage = !TextUtils.isEmpty(language);
+            final String country = systemLocale.getCountry();
+            final boolean hasCountry = !TextUtils.isEmpty(country);
+            final String variant = systemLocale.getVariant();
+            final boolean hasVariant = !TextUtils.isEmpty(variant);
+            if (hasLanguage && hasCountry && hasVariant) {
+                systemLocaleLanguageCountryVariant = new Locale(language, country, variant);
+            } else {
+                systemLocaleLanguageCountryVariant = null;
+            }
+            if (hasLanguage && hasCountry) {
+                systemLocaleLanguageCountry = new Locale(language, country);
+            } else {
+                systemLocaleLanguageCountry = null;
+            }
+            if (hasLanguage) {
+                systemLocaleLanguage = new Locale(language);
+            } else {
+                systemLocaleLanguage = null;
+            }
+        } else {
+            systemLocaleLanguageCountryVariant = null;
+            systemLocaleLanguageCountry = null;
+            systemLocaleLanguage = null;
+        }
+
+        final ArrayList<Locale> locales = new ArrayList<>();
+        if (systemLocaleLanguageCountryVariant != null) {
+            locales.add(systemLocaleLanguageCountryVariant);
+        }
+
+        if (Locale.ENGLISH.equals(systemLocaleLanguage)) {
+            if (systemLocaleLanguageCountry != null) {
+                // If the system language is English, and the region is also explicitly specified,
+                // following fallback order will be applied.
+                // - systemLocaleLanguageCountry [if systemLocaleLanguageCountry is non-null]
+                // - en_US [if systemLocaleLanguageCountry is non-null and not en_US]
+                // - en_GB [if systemLocaleLanguageCountry is non-null and not en_GB]
+                // - en
+                if (systemLocaleLanguageCountry != null) {
+                    locales.add(systemLocaleLanguageCountry);
+                }
+                if (!Locale.US.equals(systemLocaleLanguageCountry)) {
+                    locales.add(Locale.US);
+                }
+                if (!Locale.UK.equals(systemLocaleLanguageCountry)) {
+                    locales.add(Locale.UK);
+                }
+                locales.add(Locale.ENGLISH);
+            } else {
+                // If the system language is English, but no region is specified, following
+                // fallback order will be applied.
+                // - en
+                // - en_US
+                // - en_GB
+                locales.add(Locale.ENGLISH);
+                locales.add(Locale.US);
+                locales.add(Locale.UK);
+            }
+        } else {
+            // If the system language is not English, the fallback order will be
+            // - systemLocaleLanguageCountry  [if non-null]
+            // - systemLocaleLanguage  [if non-null]
+            // - en_US
+            // - en_GB
+            // - en
+            if (systemLocaleLanguageCountry != null) {
+                locales.add(systemLocaleLanguageCountry);
+            }
+            if (systemLocaleLanguage != null) {
+                locales.add(systemLocaleLanguage);
+            }
+            locales.add(Locale.US);
+            locales.add(Locale.UK);
+            locales.add(Locale.ENGLISH);
+        }
+        return locales;
+    }
 }
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index d4c4ab3..6f9c87a 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -110,12 +110,6 @@
 
     abstract protected boolean isActive();
 
-    /**
-     * Called when the user took some actions that should be taken into consideration to update the
-     * LRU list for input method rotation.
-     */
-    abstract protected void onUserAction();
-
     public void getTextAfterCursor(int length, int flags, int seq, IInputContextCallback callback) {
         dispatchMessage(obtainMessageIISC(DO_GET_TEXT_AFTER_CURSOR, length, flags, seq, callback));
     }
@@ -342,7 +336,6 @@
                     return;
                 }
                 ic.commitText((CharSequence)msg.obj, msg.arg1);
-                onUserAction();
                 return;
             }
             case DO_SET_SELECTION: {
@@ -397,7 +390,6 @@
                     return;
                 }
                 ic.setComposingText((CharSequence)msg.obj, msg.arg1);
-                onUserAction();
                 return;
             }
             case DO_SET_COMPOSING_REGION: {
@@ -437,7 +429,6 @@
                     return;
                 }
                 ic.sendKeyEvent((KeyEvent)msg.obj);
-                onUserAction();
                 return;
             }
             case DO_CLEAR_META_KEY_STATES: {
diff --git a/core/java/com/android/internal/view/IInputMethodClient.aidl b/core/java/com/android/internal/view/IInputMethodClient.aidl
index 5c6dea8..2618356 100644
--- a/core/java/com/android/internal/view/IInputMethodClient.aidl
+++ b/core/java/com/android/internal/view/IInputMethodClient.aidl
@@ -27,6 +27,5 @@
     // unbindReason corresponds to InputMethodClient.UnbindReason.
     void onUnbindMethod(int sequence, int unbindReason);
     void setActive(boolean active, boolean fullscreen);
-    void setUserActionNotificationSequenceNumber(int sequenceNumber);
     void reportFullscreenMode(boolean fullscreen);
 }
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 5afc53f..543f4a5 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -79,6 +79,4 @@
     // This is kept due to @UnsupportedAppUsage.
     // TODO(Bug 113914148): Consider removing this.
     int getInputMethodWindowVisibleHeight();
-
-    oneway void notifyUserAction(int sequenceNumber);
 }
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
index 9d4383f..7548c22 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -60,7 +60,7 @@
         /**
          * Indicates that this is a temporary binding until the
          * {@link android.inputmethodservice.InputMethodService} (IMS) establishes a valid session
-         * to {@link com.android.server.InputMethodManagerService} (IMMS).
+         * to {@link com.android.server.inputmethod.InputMethodManagerService} (IMMS).
          *
          * <p>Note that in this state the IMS is already bound to IMMS but the logical session
          * is not yet established on top of the IPC channel.</p>
@@ -73,7 +73,7 @@
         /**
          * Indicates that this is a temporary binding until the
          * {@link android.inputmethodservice.InputMethodService} (IMS) establishes a valid session
-         * to {@link com.android.server.InputMethodManagerService} (IMMS).
+         * to {@link com.android.server.inputmethod.InputMethodManagerService} (IMMS).
          *
          * <p>Note that in this state the IMMS has already initiated a connection to the IMS but
          * the binding process is not completed yet.</p>
@@ -91,12 +91,14 @@
         int SUCCESS_REPORT_WINDOW_FOCUS_ONLY = 3;
         /**
          * Indicates somehow
-         * {@link com.android.server.InputMethodManagerService#startInputOrWindowGainedFocus} is
-         * trying to return null {@link InputBindResult}, which must never happen.
+         * {@link
+         * com.android.server.inputmethod.InputMethodManagerService#startInputOrWindowGainedFocus}
+         * is trying to return null {@link InputBindResult}, which must never happen.
          */
         int ERROR_NULL = 4;
         /**
-         * Indicates that {@link com.android.server.InputMethodManagerService} recognizes no IME.
+         * Indicates that {@link com.android.server.inputmethod.InputMethodManagerService}
+         * recognizes no IME.
          */
         int ERROR_NO_IME = 5;
         /**
@@ -114,8 +116,8 @@
          */
         int ERROR_SYSTEM_NOT_READY = 7;
         /**
-         * Indicates that {@link com.android.server.InputMethodManagerService} tried to connect to
-         * an {@link android.inputmethodservice.InputMethodService} but failed.
+         * Indicates that {@link com.android.server.inputmethod.InputMethodManagerService} tried to
+         * connect to an {@link android.inputmethodservice.InputMethodService} but failed.
          *
          * @see android.content.Context#bindServiceAsUser(Intent, ServiceConnection, int, UserHandle)
          */
@@ -137,7 +139,8 @@
          * The client should try to restart input when its {@link android.view.Window} is focused
          * again.</p>
          *
-         * @see com.android.server.wm.WindowManagerService#inputMethodClientHasFocus(IInputMethodClient)
+         * @see com.android.server.wm.WindowManagerInternal#inputMethodClientHasFocus(
+         * IInputMethodClient)
          */
         int ERROR_NOT_IME_TARGET_WINDOW = 11;
         /**
@@ -171,20 +174,13 @@
      */
     public final int sequence;
 
-    /**
-     * Sequence number of user action notification.
-     */
-    public final int userActionNotificationSequenceNumber;
-
     public InputBindResult(@ResultCode int _result,
-            IInputMethodSession _method, InputChannel _channel,
-            String _id, int _sequence, int _userActionNotificationSequenceNumber) {
+            IInputMethodSession _method, InputChannel _channel, String _id, int _sequence) {
         result = _result;
         method = _method;
         channel = _channel;
         id = _id;
         sequence = _sequence;
-        userActionNotificationSequenceNumber = _userActionNotificationSequenceNumber;
     }
 
     InputBindResult(Parcel source) {
@@ -197,14 +193,12 @@
         }
         id = source.readString();
         sequence = source.readInt();
-        userActionNotificationSequenceNumber = source.readInt();
     }
 
     @Override
     public String toString() {
         return "InputBindResult{result=" + getResultString() + " method="+ method + " id=" + id
                 + " sequence=" + sequence
-                + " userActionNotificationSequenceNumber=" + userActionNotificationSequenceNumber
                 + "}";
     }
 
@@ -226,7 +220,6 @@
         }
         dest.writeString(id);
         dest.writeInt(sequence);
-        dest.writeInt(userActionNotificationSequenceNumber);
     }
 
     /**
@@ -285,7 +278,7 @@
     }
 
     private static InputBindResult error(@ResultCode int result) {
-        return new InputBindResult(result, null, null, null, -1, -1);
+        return new InputBindResult(result, null, null, null, -1);
     }
 
     /**
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 5b65bbe..3bd3072 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -371,6 +371,7 @@
     public boolean commitText(CharSequence text, int newCursorPosition) {
         try {
             mIInputContext.commitText(text, newCursorPosition);
+            notifyUserActionIfNecessary();
             return true;
         } catch (RemoteException e) {
             return false;
@@ -378,6 +379,16 @@
     }
 
     @AnyThread
+    private void notifyUserActionIfNecessary() {
+        final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+        if (inputMethodService == null) {
+            // This basically should not happen, because it's the the caller of this method.
+            return;
+        }
+        inputMethodService.notifyUserActionIfNecessary();
+    }
+
+    @AnyThread
     public boolean commitCompletion(CompletionInfo text) {
         if (isMethodMissing(MissingMethodFlags.COMMIT_CORRECTION)) {
             // This method is not implemented.
@@ -449,6 +460,7 @@
     public boolean setComposingText(CharSequence text, int newCursorPosition) {
         try {
             mIInputContext.setComposingText(text, newCursorPosition);
+            notifyUserActionIfNecessary();
             return true;
         } catch (RemoteException e) {
             return false;
@@ -489,6 +501,7 @@
     public boolean sendKeyEvent(KeyEvent event) {
         try {
             mIInputContext.sendKeyEvent(event);
+            notifyUserActionIfNecessary();
             return true;
         } catch (RemoteException e) {
             return false;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f845bd0..9ab55d6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -584,7 +584,7 @@
     <protected-broadcast android:name="android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED" />
     <protected-broadcast android:name="android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED" />
     <protected-broadcast android:name="android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED" />
-    <protected-broadcast android:name="com.android.server.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER" />
+    <protected-broadcast android:name="com.android.server.inputmethod.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER" />
 
     <!-- Time zone rules update intents fired by the system server -->
     <protected-broadcast android:name="com.android.intent.action.timezone.RULES_UPDATE_OPERATION" />
@@ -3352,7 +3352,7 @@
           @hide
           @removed -->
     <permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to know what content is playing and control its playback.
          <p>Not for use by third-party applications due to privacy of media consumption</p>  -->
@@ -4120,11 +4120,6 @@
     <permission android:name="android.permission.DISABLE_HIDDEN_API_CHECKS"
                 android:protectionLevel="signature" />
 
-    <!-- Allows an application to read emergency info name.
-         @hide <p>Not for use by third-party applications. -->
-    <permission android:name="com.android.emergency.permission.READ_EMERGENCY_INFO_NAME"
-                android:protectionLevel="signature" />
-
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
diff --git a/core/res/res/values-night/themes_device_defaults.xml b/core/res/res/values-night/themes_device_defaults.xml
index 5e3675a..c8d4d05 100644
--- a/core/res/res/values-night/themes_device_defaults.xml
+++ b/core/res/res/values-night/themes_device_defaults.xml
@@ -51,4 +51,7 @@
           -->
     <!-- DeviceDefault theme for a window that should look like the Settings app.  -->
     <style name="Theme.DeviceDefault.Settings" parent="Theme.DeviceDefault"/>
+
+    <!-- Theme for the dialog shown when an app crashes or ANRs. -->
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert" />
 </resources>
diff --git a/core/res/res/values-television/themes.xml b/core/res/res/values-television/themes.xml
index 377982a..0712cbc 100644
--- a/core/res/res/values-television/themes.xml
+++ b/core/res/res/values-television/themes.xml
@@ -15,7 +15,7 @@
 -->
 <resources>
     <style name="Theme.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
-    <style name="Theme.Dialog.AppError" parent="Theme.Leanback.Dialog.AppError" />
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.Leanback.Dialog.AppError" />
     <style name="Theme.Holo.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
     <style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
     <style name="Theme.Material.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
diff --git a/core/res/res/values-watch/themes.xml b/core/res/res/values-watch/themes.xml
index 04df180..1be47ba 100644
--- a/core/res/res/values-watch/themes.xml
+++ b/core/res/res/values-watch/themes.xml
@@ -15,7 +15,7 @@
 -->
 <resources>
     <!-- Theme for the dialog shown when an app crashes or ANRs. Override to make it dark. -->
-    <style name="Theme.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert">
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert">
         <item name="windowContentTransitions">false</item>
         <item name="windowActivityTransitions">false</item>
         <item name="windowCloseOnTouchOutside">false</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 92cca72..389278f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2099,7 +2099,7 @@
   <java-symbol type="string" name="vpn_lockdown_error" />
   <java-symbol type="string" name="vpn_lockdown_config" />
   <java-symbol type="string" name="wallpaper_binding_label" />
-  <java-symbol type="style" name="Theme.Dialog.AppError" />
+  <java-symbol type="style" name="Theme.DeviceDefault.Dialog.AppError" />
   <java-symbol type="style" name="Theme.Leanback.Dialog.Alert" />
   <java-symbol type="style" name="Theme.Toast" />
   <java-symbol type="xml" name="storage_list" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 3937af5..a7530ce 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -869,13 +869,6 @@
     <!-- System themes -->
     <eat-comment />
 
-    <!-- Theme for the dialog shown when an app crashes or ANRs. -->
-    <style name="Theme.Dialog.AppError" parent="Theme.DeviceDefault.Light.Dialog.Alert">
-        <item name="windowContentTransitions">false</item>
-        <item name="windowActivityTransitions">false</item>
-        <item name="windowCloseOnTouchOutside">false</item>
-    </style>
-
     <!-- Special theme for the recent apps dialog, to allow customization
          with overlays. -->
     <style name="Theme.Dialog.RecentApplications" parent="Theme.DeviceDefault.Light.Dialog">
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 14e5082..92096ab 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -719,6 +719,13 @@
         <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
     </style>
 
+    <!-- Theme for the dialog shown when an app crashes or ANRs. -->
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Light.Dialog.Alert">
+        <item name="windowContentTransitions">false</item>
+        <item name="windowActivityTransitions">false</item>
+        <item name="windowCloseOnTouchOutside">false</item>
+    </style>
+
     <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Material.SearchBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
diff --git a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
index 5ef30a8..dcc51e1 100644
--- a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
+++ b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
@@ -48,8 +48,8 @@
 
     @Test
     public void testSetCurveIsUnmodified() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, NITS_LEVELS);
+        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
+                LUX_LEVELS, NITS_LEVELS);
         BrightnessConfiguration config = builder.build();
         Pair<float[], float[]> curve = config.getCurve();
         assertArrayEquals(LUX_LEVELS, curve.first, "lux");
@@ -58,45 +58,33 @@
 
     @Test(expected = IllegalArgumentException.class)
     public void testCurveMustHaveZeroLuxPoint() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
         float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length);
         lux[0] = 1f;
-        builder.setCurve(lux, NITS_LEVELS);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testCurveMustBeSet() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.build();
+        new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
     }
 
     @Test(expected = NullPointerException.class)
     public void testCurveMustNotHaveNullArrays() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(null, null);
+        new BrightnessConfiguration.Builder(null, null);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testCurveMustNotHaveEmptyArrays() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(new float[0], new float[0]);
+        new BrightnessConfiguration.Builder(new float[0], new float[0]);
     }
 
     @Test
     public void testCurveMustNotHaveArraysOfDifferentLengths() {
         assertThrows(IllegalArgumentException.class, () -> {
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
             float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length + 1);
             lux[lux.length - 1] = lux[lux.length - 2] + 1;
-            boolean exceptionThrown = false;
-            builder.setCurve(lux, NITS_LEVELS);
+            new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
         });
 
         assertThrows(IllegalArgumentException.class, () -> {
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
             float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length + 1);
             nits[nits.length - 1] = nits[nits.length - 2] + 1;
-            builder.setCurve(LUX_LEVELS, nits);
+            new BrightnessConfiguration.Builder(LUX_LEVELS, nits);
         });
     }
 
@@ -105,23 +93,21 @@
         assertThrows(IllegalArgumentException.class, () -> {
             float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length);
             lux[lux.length - 1] = Float.NaN;
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-            builder.setCurve(lux, NITS_LEVELS);
+            new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
         });
 
         assertThrows(IllegalArgumentException.class, () -> {
             float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length);
             nits[nits.length - 1] = Float.NaN;
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-            builder.setCurve(LUX_LEVELS, nits);
+            new BrightnessConfiguration.Builder(LUX_LEVELS, nits);
         });
     }
 
 
     @Test
     public void testParceledConfigIsEquivalent() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, NITS_LEVELS);
+        BrightnessConfiguration.Builder builder =
+                new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
         BrightnessConfiguration config = builder.build();
         Parcel p = Parcel.obtain();
         p.writeParcelable(config, 0 /*flags*/);
@@ -133,12 +119,11 @@
 
     @Test
     public void testEquals() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, NITS_LEVELS);
+        BrightnessConfiguration.Builder builder =
+                new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
         BrightnessConfiguration baseConfig = builder.build();
 
-        builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, NITS_LEVELS);
+        builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
         BrightnessConfiguration identicalConfig = builder.build();
         assertEquals(baseConfig, identicalConfig);
         assertEquals("hashCodes must be equal for identical configs",
@@ -146,15 +131,13 @@
 
         float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length);
         lux[lux.length - 1] = lux[lux.length - 1] * 2;
-        builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(lux, NITS_LEVELS);
+        builder = new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
         BrightnessConfiguration luxDifferConfig = builder.build();
         assertNotEquals(baseConfig, luxDifferConfig);
 
         float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length);
         nits[nits.length - 1] = nits[nits.length - 1] * 2;
-        builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, nits);
+        builder = new BrightnessConfiguration.Builder(LUX_LEVELS, nits);
         BrightnessConfiguration nitsDifferConfig = builder.build();
         assertNotEquals(baseConfig, nitsDifferConfig);
     }
diff --git a/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java b/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java
index 920988b..9e44554 100644
--- a/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java
+++ b/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java
@@ -24,7 +24,6 @@
 import android.provider.Settings;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
 
 /**
  * Tests ActivityManager#setPersistentVrThread and ActivityManager#setVrThread's
@@ -76,9 +75,11 @@
     }
 
     private void setPersistentVrModeEnabled(boolean enable) throws Throwable {
-        mVrManager.setPersistentVrModeEnabled(enable);
-        // Allow the system time to send out callbacks for persistent VR mode.
-        Thread.sleep(200);
+        if (mVrManager != null) {
+            mVrManager.setPersistentVrModeEnabled(enable);
+            // Allow the system time to send out callbacks for persistent VR mode.
+            Thread.sleep(200);
+        }
     }
 
     @SmallTest
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
index 3064afa..f731a4a 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
@@ -71,15 +71,11 @@
     private static final Locale LOCALE_FR = new Locale("fr");
     private static final Locale LOCALE_FR_CA = new Locale("fr", "CA");
     private static final Locale LOCALE_HI = new Locale("hi");
-    private static final Locale LOCALE_JA = new Locale("ja");
     private static final Locale LOCALE_JA_JP = new Locale("ja", "JP");
     private static final Locale LOCALE_ZH_CN = new Locale("zh", "CN");
     private static final Locale LOCALE_ZH_TW = new Locale("zh", "TW");
     private static final Locale LOCALE_IN = new Locale("in");
     private static final Locale LOCALE_ID = new Locale("id");
-    private static final Locale LOCALE_TH = new Locale("ht");
-    private static final Locale LOCALE_TH_TH = new Locale("ht", "TH");
-    private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH");
     private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
     private static final String SUBTYPE_MODE_VOICE = "voice";
     private static final String SUBTYPE_MODE_HANDWRITING = "handwriting";
@@ -1087,122 +1083,6 @@
     }
 
     @Test
-    public void testGetSuitableLocalesForSpellChecker() throws Exception {
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_US);
-            assertEquals(3, locales.size());
-            assertEquals(LOCALE_EN_US, locales.get(0));
-            assertEquals(LOCALE_EN_GB, locales.get(1));
-            assertEquals(LOCALE_EN, locales.get(2));
-        }
-
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_GB);
-            assertEquals(3, locales.size());
-            assertEquals(LOCALE_EN_GB, locales.get(0));
-            assertEquals(LOCALE_EN_US, locales.get(1));
-            assertEquals(LOCALE_EN, locales.get(2));
-        }
-
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN);
-            assertEquals(3, locales.size());
-            assertEquals(LOCALE_EN, locales.get(0));
-            assertEquals(LOCALE_EN_US, locales.get(1));
-            assertEquals(LOCALE_EN_GB, locales.get(2));
-        }
-
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_IN);
-            assertEquals(4, locales.size());
-            assertEquals(LOCALE_EN_IN, locales.get(0));
-            assertEquals(LOCALE_EN_US, locales.get(1));
-            assertEquals(LOCALE_EN_GB, locales.get(2));
-            assertEquals(LOCALE_EN, locales.get(3));
-        }
-
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_JA_JP);
-            assertEquals(5, locales.size());
-            assertEquals(LOCALE_JA_JP, locales.get(0));
-            assertEquals(LOCALE_JA, locales.get(1));
-            assertEquals(LOCALE_EN_US, locales.get(2));
-            assertEquals(LOCALE_EN_GB, locales.get(3));
-            assertEquals(Locale.ENGLISH, locales.get(4));
-        }
-
-        // Test 3-letter language code.
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_FIL_PH);
-            assertEquals(5, locales.size());
-            assertEquals(LOCALE_FIL_PH, locales.get(0));
-            assertEquals(LOCALE_FIL, locales.get(1));
-            assertEquals(LOCALE_EN_US, locales.get(2));
-            assertEquals(LOCALE_EN_GB, locales.get(3));
-            assertEquals(Locale.ENGLISH, locales.get(4));
-        }
-
-        // Test variant.
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_TH_TH_TH);
-            assertEquals(6, locales.size());
-            assertEquals(LOCALE_TH_TH_TH, locales.get(0));
-            assertEquals(LOCALE_TH_TH, locales.get(1));
-            assertEquals(LOCALE_TH, locales.get(2));
-            assertEquals(LOCALE_EN_US, locales.get(3));
-            assertEquals(LOCALE_EN_GB, locales.get(4));
-            assertEquals(Locale.ENGLISH, locales.get(5));
-        }
-
-        // Test Locale extension.
-        {
-            final Locale localeWithoutVariant = LOCALE_JA_JP;
-            final Locale localeWithVariant = new Locale.Builder()
-                    .setLocale(LOCALE_JA_JP)
-                    .setExtension('x', "android")
-                    .build();
-            assertFalse(localeWithoutVariant.equals(localeWithVariant));
-
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(localeWithVariant);
-            assertEquals(5, locales.size());
-            assertEquals(LOCALE_JA_JP, locales.get(0));
-            assertEquals(LOCALE_JA, locales.get(1));
-            assertEquals(LOCALE_EN_US, locales.get(2));
-            assertEquals(LOCALE_EN_GB, locales.get(3));
-            assertEquals(Locale.ENGLISH, locales.get(4));
-        }
-    }
-
-    @Test
-    public void testConstructLocaleFromString() throws Exception {
-        assertEquals(new Locale("en"), InputMethodUtils.constructLocaleFromString("en"));
-        assertEquals(new Locale("en", "US"), InputMethodUtils.constructLocaleFromString("en_US"));
-        assertEquals(new Locale("en", "US", "POSIX"),
-                InputMethodUtils.constructLocaleFromString("en_US_POSIX"));
-
-        // Special rewrite rule for "tl" for versions of Android earlier than Lollipop that did not
-        // support three letter language codes, and used "tl" (Tagalog) as the language string for
-        // "fil" (Filipino).
-        assertEquals(new Locale("fil"), InputMethodUtils.constructLocaleFromString("tl"));
-        assertEquals(new Locale("fil", "PH"), InputMethodUtils.constructLocaleFromString("tl_PH"));
-        assertEquals(new Locale("fil", "PH", "POSIX"),
-                InputMethodUtils.constructLocaleFromString("tl_PH_POSIX"));
-
-        // So far rejecting an invalid/unexpected locale string is out of the scope of this method.
-        assertEquals(new Locale("a"), InputMethodUtils.constructLocaleFromString("a"));
-        assertEquals(new Locale("a b c"), InputMethodUtils.constructLocaleFromString("a b c"));
-        assertEquals(new Locale("en-US"), InputMethodUtils.constructLocaleFromString("en-US"));
-    }
-
-    @Test
     public void testIsSoftInputModeStateVisibleAllowed() {
         // On pre-P devices, SOFT_INPUT_STATE_VISIBLE/SOFT_INPUT_STATE_ALWAYS_VISIBLE are always
         // allowed, regardless of the focused view state.
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java
index 549511a..7d0e646 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java
@@ -17,6 +17,7 @@
 package com.android.internal.inputmethod;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 
 import android.os.LocaleList;
 import android.support.test.filters.SmallTest;
@@ -34,6 +35,18 @@
 
     private static final LocaleUtils.LocaleExtractor<Locale> sIdentityMapper = source -> source;
 
+    private static final Locale LOCALE_EN = new Locale("en");
+    private static final Locale LOCALE_EN_US = new Locale("en", "US");
+    private static final Locale LOCALE_EN_GB = new Locale("en", "GB");
+    private static final Locale LOCALE_EN_IN = new Locale("en", "IN");
+    private static final Locale LOCALE_FIL = new Locale("fil");
+    private static final Locale LOCALE_FIL_PH = new Locale("fil", "PH");
+    private static final Locale LOCALE_JA = new Locale("ja");
+    private static final Locale LOCALE_JA_JP = new Locale("ja", "JP");
+    private static final Locale LOCALE_TH = new Locale("ht");
+    private static final Locale LOCALE_TH_TH = new Locale("ht", "TH");
+    private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH");
+
     @Test
     public void testFilterByLanguageEmptyLanguageList() throws Exception {
         final ArrayList<Locale> availableLocales = new ArrayList<>();
@@ -385,4 +398,120 @@
             assertEquals(availableLocales.get(3), dest.get(0));
         }
     }
+
+    @Test
+    public void testGetSuitableLocalesForSpellChecker() throws Exception {
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_US);
+            assertEquals(3, locales.size());
+            assertEquals(LOCALE_EN_US, locales.get(0));
+            assertEquals(LOCALE_EN_GB, locales.get(1));
+            assertEquals(LOCALE_EN, locales.get(2));
+        }
+
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_GB);
+            assertEquals(3, locales.size());
+            assertEquals(LOCALE_EN_GB, locales.get(0));
+            assertEquals(LOCALE_EN_US, locales.get(1));
+            assertEquals(LOCALE_EN, locales.get(2));
+        }
+
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_EN);
+            assertEquals(3, locales.size());
+            assertEquals(LOCALE_EN, locales.get(0));
+            assertEquals(LOCALE_EN_US, locales.get(1));
+            assertEquals(LOCALE_EN_GB, locales.get(2));
+        }
+
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_IN);
+            assertEquals(4, locales.size());
+            assertEquals(LOCALE_EN_IN, locales.get(0));
+            assertEquals(LOCALE_EN_US, locales.get(1));
+            assertEquals(LOCALE_EN_GB, locales.get(2));
+            assertEquals(LOCALE_EN, locales.get(3));
+        }
+
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_JA_JP);
+            assertEquals(5, locales.size());
+            assertEquals(LOCALE_JA_JP, locales.get(0));
+            assertEquals(LOCALE_JA, locales.get(1));
+            assertEquals(LOCALE_EN_US, locales.get(2));
+            assertEquals(LOCALE_EN_GB, locales.get(3));
+            assertEquals(Locale.ENGLISH, locales.get(4));
+        }
+
+        // Test 3-letter language code.
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_FIL_PH);
+            assertEquals(5, locales.size());
+            assertEquals(LOCALE_FIL_PH, locales.get(0));
+            assertEquals(LOCALE_FIL, locales.get(1));
+            assertEquals(LOCALE_EN_US, locales.get(2));
+            assertEquals(LOCALE_EN_GB, locales.get(3));
+            assertEquals(Locale.ENGLISH, locales.get(4));
+        }
+
+        // Test variant.
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_TH_TH_TH);
+            assertEquals(6, locales.size());
+            assertEquals(LOCALE_TH_TH_TH, locales.get(0));
+            assertEquals(LOCALE_TH_TH, locales.get(1));
+            assertEquals(LOCALE_TH, locales.get(2));
+            assertEquals(LOCALE_EN_US, locales.get(3));
+            assertEquals(LOCALE_EN_GB, locales.get(4));
+            assertEquals(Locale.ENGLISH, locales.get(5));
+        }
+
+        // Test Locale extension.
+        {
+            final Locale localeWithoutVariant = LOCALE_JA_JP;
+            final Locale localeWithVariant = new Locale.Builder()
+                    .setLocale(LOCALE_JA_JP)
+                    .setExtension('x', "android")
+                    .build();
+            assertFalse(localeWithoutVariant.equals(localeWithVariant));
+
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(localeWithVariant);
+            assertEquals(5, locales.size());
+            assertEquals(LOCALE_JA_JP, locales.get(0));
+            assertEquals(LOCALE_JA, locales.get(1));
+            assertEquals(LOCALE_EN_US, locales.get(2));
+            assertEquals(LOCALE_EN_GB, locales.get(3));
+            assertEquals(Locale.ENGLISH, locales.get(4));
+        }
+    }
+
+    @Test
+    public void testConstructLocaleFromString() throws Exception {
+        assertEquals(new Locale("en"), LocaleUtils.constructLocaleFromString("en"));
+        assertEquals(new Locale("en", "US"), LocaleUtils.constructLocaleFromString("en_US"));
+        assertEquals(new Locale("en", "US", "POSIX"),
+                LocaleUtils.constructLocaleFromString("en_US_POSIX"));
+
+        // Special rewrite rule for "tl" for versions of Android earlier than Lollipop that did not
+        // support three letter language codes, and used "tl" (Tagalog) as the language string for
+        // "fil" (Filipino).
+        assertEquals(new Locale("fil"), LocaleUtils.constructLocaleFromString("tl"));
+        assertEquals(new Locale("fil", "PH"), LocaleUtils.constructLocaleFromString("tl_PH"));
+        assertEquals(new Locale("fil", "PH", "POSIX"),
+                LocaleUtils.constructLocaleFromString("tl_PH_POSIX"));
+
+        // So far rejecting an invalid/unexpected locale string is out of the scope of this method.
+        assertEquals(new Locale("a"), LocaleUtils.constructLocaleFromString("a"));
+        assertEquals(new Locale("a b c"), LocaleUtils.constructLocaleFromString("a b c"));
+        assertEquals(new Locale("en-US"), LocaleUtils.constructLocaleFromString("en-US"));
+    }
 }
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 0476222..5ad7365 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -715,6 +715,7 @@
                     break;
                 case AudioSystem.STREAM_TTS:
                     mContentType = CONTENT_TYPE_SONIFICATION;
+                    mFlags |= FLAG_BEACON;
                     break;
                 case AudioSystem.STREAM_ACCESSIBILITY:
                     mContentType = CONTENT_TYPE_SPEECH;
@@ -1039,6 +1040,10 @@
             return fromGetVolumeControlStream ?
                     AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_BLUETOOTH_SCO;
         }
+        if ((aa.getAllFlags() & FLAG_BEACON) == FLAG_BEACON) {
+            return fromGetVolumeControlStream ?
+                    AudioSystem.STREAM_MUSIC : AudioSystem.STREAM_TTS;
+        }
 
         // usage to stream type mapping
         switch (aa.getUsage()) {
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 339a7ee..7681cc3 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -91,6 +91,7 @@
         "android_media_Media2HTTPConnection.cpp",
         "android_media_Media2HTTPService.cpp",
         "android_media_Media2DataSource.cpp",
+        "android_media_MediaMetricsJNI.cpp",
         "android_media_MediaPlayer2.cpp",
         "android_media_SyncParams.cpp",
     ],
@@ -98,7 +99,6 @@
     shared_libs: [
         "android.hardware.cas@1.0",  // for CasManager. VNDK???
         "android.hardware.cas.native@1.0",  // CasManager. VNDK???
-        "libandroid_runtime",  // ???
         "libaudioclient",  // for use of AudioTrack, AudioSystem. to be removed
         "libbinder",
         "libgui",  // for VideoFrameScheduler
@@ -120,13 +120,9 @@
     header_libs: ["libhardware_headers"],
 
     static_libs: [
-        "libbacktrace",
         "libbase",
-        "libc_malloc_debug_backtrace",
         "libcrypto",
         "libcutils",
-        "libdexfile",
-        "liblzma",
         "libmedia_helper",
         "libmedia_player2_util",
         "libmediadrm",
@@ -135,7 +131,7 @@
         "libmediaplayer2",
         "libmediaplayer2-protos",
         "libmediautils",
-        "libnetd_client",
+        "libnetd_client",  // for setNetworkForUser
         "libprotobuf-cpp-lite",
         "libstagefright_esds",
         "libstagefright_foundation",
@@ -146,9 +142,6 @@
         "libstagefright_player2",
         "libstagefright_rtsp",
         "libstagefright_timedtext2",
-        "libunwindstack",
-        "libutilscallstack",
-        "libziparchive",
     ],
 
     group_static_libs: true,
diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp
new file mode 100644
index 0000000..3ded8c2
--- /dev/null
+++ b/media/jni/android_media_MediaMetricsJNI.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2017, 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.
+ */
+
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+
+#include "android_media_MediaMetricsJNI.h"
+#include <media/MediaAnalyticsItem.h>
+
+
+// Copeid from core/jni/ (libandroid_runtime.so)
+namespace android {
+
+// place the attributes into a java PersistableBundle object
+jobject MediaMetricsJNI::writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle) {
+
+    jclass clazzBundle = env->FindClass("android/os/PersistableBundle");
+    if (clazzBundle==NULL) {
+        ALOGD("can't find android/os/PersistableBundle");
+        return NULL;
+    }
+    // sometimes the caller provides one for us to fill
+    if (mybundle == NULL) {
+        // create the bundle
+        jmethodID constructID = env->GetMethodID(clazzBundle, "<init>", "()V");
+        mybundle = env->NewObject(clazzBundle, constructID);
+        if (mybundle == NULL) {
+            return NULL;
+        }
+    }
+
+    // grab methods that we can invoke
+    jmethodID setIntID = env->GetMethodID(clazzBundle, "putInt", "(Ljava/lang/String;I)V");
+    jmethodID setLongID = env->GetMethodID(clazzBundle, "putLong", "(Ljava/lang/String;J)V");
+    jmethodID setDoubleID = env->GetMethodID(clazzBundle, "putDouble", "(Ljava/lang/String;D)V");
+    jmethodID setStringID = env->GetMethodID(clazzBundle, "putString", "(Ljava/lang/String;Ljava/lang/String;)V");
+
+    // env, class, method, {parms}
+    //env->CallVoidMethod(env, mybundle, setIntID, jstr, jint);
+
+    // iterate through my attributes
+    // -- get name, get type, get value
+    // -- insert appropriately into the bundle
+    for (size_t i = 0 ; i < item->mPropCount; i++ ) {
+            MediaAnalyticsItem::Prop *prop = &item->mProps[i];
+            // build the key parameter from prop->mName
+            jstring keyName = env->NewStringUTF(prop->mName);
+            // invoke the appropriate method to insert
+            switch (prop->mType) {
+                case MediaAnalyticsItem::kTypeInt32:
+                    env->CallVoidMethod(mybundle, setIntID,
+                                        keyName, (jint) prop->u.int32Value);
+                    break;
+                case MediaAnalyticsItem::kTypeInt64:
+                    env->CallVoidMethod(mybundle, setLongID,
+                                        keyName, (jlong) prop->u.int64Value);
+                    break;
+                case MediaAnalyticsItem::kTypeDouble:
+                    env->CallVoidMethod(mybundle, setDoubleID,
+                                        keyName, (jdouble) prop->u.doubleValue);
+                    break;
+                case MediaAnalyticsItem::kTypeCString:
+                    env->CallVoidMethod(mybundle, setStringID, keyName,
+                                        env->NewStringUTF(prop->u.CStringValue));
+                    break;
+                default:
+                        ALOGE("to_String bad item type: %d for %s",
+                              prop->mType, prop->mName);
+                        break;
+            }
+    }
+
+    return mybundle;
+}
+
+};  // namespace android
+
diff --git a/media/jni/android_media_MediaMetricsJNI.h b/media/jni/android_media_MediaMetricsJNI.h
new file mode 100644
index 0000000..fd621ea
--- /dev/null
+++ b/media/jni/android_media_MediaMetricsJNI.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
+#define _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
+
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <media/MediaAnalyticsItem.h>
+
+// Copeid from core/jni/ (libandroid_runtime.so)
+namespace android {
+
+class MediaMetricsJNI {
+public:
+    static jobject writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle);
+};
+
+};  // namespace android
+
+#endif //  _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index d33f6db..d4c84b5 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -909,7 +909,7 @@
 }
 
 static jboolean
-android_media_MediaPlayer2_setParameter(JNIEnv *env, jobject thiz, jint key, jobject java_request)
+android_media_MediaPlayer2_setParameter(JNIEnv *env, jobject thiz, jint key, jobject)
 {
     ALOGV("setParameter: key %d", key);
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
@@ -918,9 +918,11 @@
         return false;
     }
 
-    // TODO: parcelForJavaObject() shouldn't be used since it's dependent on
-    //       framework's Parcel implementation. This setParameter() is used
-    //       only with AudioAttribute. Can this be used as jobject with JAudioTrack?
+    return false;
+    // TODO: set/getParameter is temporarily disabled to remove android_runtime.so dependency.
+    //       Once JAudioTrack migration is done, the AudioAttribute jobject
+    //       should be directly passed to AudioTrack without native parcel conversion.
+    /*
     Parcel *request = parcelForJavaObject(env, java_request);
     status_t err = mp->setParameter(key, *request);
     if (err == OK) {
@@ -928,6 +930,7 @@
     } else {
         return false;
     }
+    */
 }
 
 static jobject
@@ -940,6 +943,11 @@
         return NULL;
     }
 
+    return NULL;
+    // TODO: set/getParameter is temporarily disabled to remove android_runtime.so dependency.
+    //       Once JAudioTrack migration is done, the AudioAttribute jobject
+    //       should be directly passed to AudioTrack without native parcel conversion.
+    /*
     jobject jParcel = createJavaParcelObject(env);
     if (jParcel != NULL) {
         Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
@@ -950,6 +958,7 @@
         }
     }
     return jParcel;
+    */
 }
 
 static void
@@ -1023,55 +1032,6 @@
     return out;
 }
 
-// Sends the new filter to the client.
-static jint
-android_media_MediaPlayer2_setMetadataFilter(JNIEnv *env, jobject thiz, jobject request)
-{
-    sp<MediaPlayer2> media_player = getMediaPlayer(env, thiz);
-    if (media_player == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return UNKNOWN_ERROR;
-    }
-
-    Parcel *filter = parcelForJavaObject(env, request);
-
-    if (filter == NULL ) {
-        jniThrowException(env, "java/lang/RuntimeException", "Filter is null");
-        return UNKNOWN_ERROR;
-    }
-
-    return (jint) media_player->setMetadataFilter(*filter);
-}
-
-static jboolean
-android_media_MediaPlayer2_getMetadata(JNIEnv *env, jobject thiz, jboolean update_only,
-                                      jboolean apply_filter, jobject reply)
-{
-    sp<MediaPlayer2> media_player = getMediaPlayer(env, thiz);
-    if (media_player == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return JNI_FALSE;
-    }
-
-    Parcel *metadata = parcelForJavaObject(env, reply);
-
-    if (metadata == NULL ) {
-        jniThrowException(env, "java/lang/RuntimeException", "Reply parcel is null");
-        return JNI_FALSE;
-    }
-
-    metadata->freeData();
-    // On return metadata is positioned at the beginning of the
-    // metadata. Note however that the parcel actually starts with the
-    // return code so you should not rewind the parcel using
-    // setDataPosition(0).
-    if (media_player->getMetadata(update_only, apply_filter, metadata) == OK) {
-        return JNI_TRUE;
-    } else {
-        return JNI_FALSE;
-    }
-}
-
 // This function gets some field IDs, which in turn causes class initialization.
 // It is called from a static block in MediaPlayer2, which won't run until the
 // first time an instance of this class is used.
@@ -1536,8 +1496,6 @@
     {"isLooping",           "()Z",                              (void *)android_media_MediaPlayer2_isLooping},
     {"_setVolume",          "(FF)V",                            (void *)android_media_MediaPlayer2_setVolume},
     {"_invoke",             "([B)[B",                           (void *)android_media_MediaPlayer2_invoke},
-    {"native_setMetadataFilter", "(Landroid/os/Parcel;)I",      (void *)android_media_MediaPlayer2_setMetadataFilter},
-    {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z",          (void *)android_media_MediaPlayer2_getMetadata},
     {"native_init",         "()V",                              (void *)android_media_MediaPlayer2_native_init},
     {"native_setup",        "(Ljava/lang/Object;)V",            (void *)android_media_MediaPlayer2_native_setup},
     {"native_finalize",     "()V",                              (void *)android_media_MediaPlayer2_native_finalize},
diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp
index f908595..86f9032 100644
--- a/packages/CarSystemUI/Android.bp
+++ b/packages/CarSystemUI/Android.bp
@@ -51,6 +51,7 @@
     libs: [
         "telephony-common",
         "android.car",
+        "android.car.user",
     ],
 
     manifest: "AndroidManifest.xml",
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
index 0c4e02b..e13e566 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
@@ -33,7 +33,6 @@
 
 final class A2dpSinkProfile implements LocalBluetoothProfile {
     private static final String TAG = "A2dpSinkProfile";
-    private static boolean V = true;
 
     private BluetoothA2dpSink mService;
     private boolean mIsProfileReady;
@@ -56,7 +55,7 @@
             implements BluetoothProfile.ServiceListener {
 
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (V) Log.d(TAG,"Bluetooth service connected");
+            Log.d(TAG, "Bluetooth service connected");
             mService = (BluetoothA2dpSink) proxy;
             // We just bound to the service, so refresh the UI for any connected A2DP devices.
             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -75,7 +74,7 @@
         }
 
         public void onServiceDisconnected(int profile) {
-            if (V) Log.d(TAG,"Bluetooth service disconnected");
+            Log.d(TAG, "Bluetooth service disconnected");
             mIsProfileReady=false;
         }
     }
@@ -106,7 +105,9 @@
     }
 
     public List<BluetoothDevice> getConnectedDevices() {
-        if (mService == null) return new ArrayList<BluetoothDevice>(0);
+        if (mService == null) {
+            return new ArrayList<BluetoothDevice>(0);
+        }
         return mService.getDevicesMatchingConnectionStates(
               new int[] {BluetoothProfile.STATE_CONNECTED,
                          BluetoothProfile.STATE_CONNECTING,
@@ -114,24 +115,18 @@
     }
 
     public boolean connect(BluetoothDevice device) {
-        if (mService == null) return false;
-        List<BluetoothDevice> srcs = getConnectedDevices();
-        if (srcs != null) {
-            for (BluetoothDevice src : srcs) {
-                if (src.equals(device)) {
-                    // Connect to same device, Ignore it
-                    Log.d(TAG,"Ignoring Connect");
-                    return true;
-                }
-            }
+        if (mService == null) {
+            return false;
         }
         return mService.connect(device);
     }
 
     public boolean disconnect(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         // Downgrade priority as user is disconnecting the headset.
-        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
+        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
             mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
         }
         return mService.disconnect(device);
@@ -145,17 +140,23 @@
     }
 
     public boolean isPreferred(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
     }
 
     public int getPreferred(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+        if (mService == null) {
+            return BluetoothProfile.PRIORITY_OFF;
+        }
         return mService.getPriority(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
-        if (mService == null) return;
+        if (mService == null) {
+            return;
+        }
         if (preferred) {
             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -166,7 +167,9 @@
     }
 
     boolean isA2dpPlaying() {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         List<BluetoothDevice> srcs = mService.getConnectedDevices();
         if (!srcs.isEmpty()) {
             if (mService.isA2dpPlaying(srcs.get(0))) {
@@ -208,7 +211,7 @@
     }
 
     protected void finalize() {
-        if (V) Log.d(TAG, "finalize()");
+        Log.d(TAG, "finalize()");
         if (mService != null) {
             try {
                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.A2DP_SINK,
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 649900b..b9f7323 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -78,12 +78,6 @@
 
     private final static String MESSAGE_REJECTION_COUNT_PREFS_NAME = "bluetooth_message_reject";
 
-    /**
-     * When we connect to multiple profiles, we only want to display a single
-     * error even if they all fail. This tracks that state.
-     */
-    private boolean mIsConnectingErrorPossible;
-
     public long getHiSyncId() {
         return mHiSyncId;
     }
@@ -230,9 +224,6 @@
             return;
         }
 
-        // Reset the only-show-one-error-dialog tracking variable
-        mIsConnectingErrorPossible = true;
-
         int preferredProfiles = 0;
         for (LocalBluetoothProfile profile : mProfiles) {
             if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) {
@@ -253,8 +244,6 @@
         if (!ensurePaired()) {
             return;
         }
-        // Reset the only-show-one-error-dialog tracking variable
-        mIsConnectingErrorPossible = true;
 
         for (LocalBluetoothProfile profile : mProfiles) {
             if (profile.isAutoConnectable()) {
@@ -271,8 +260,6 @@
      */
     public void connectProfile(LocalBluetoothProfile profile) {
         mConnectAttempted = SystemClock.elapsedRealtime();
-        // Reset the only-show-one-error-dialog tracking variable
-        mIsConnectingErrorPossible = true;
         connectInt(profile);
         // Refresh the UI based on profile.connect() call
         refresh();
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
index f9f6233..4b6a22c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
@@ -36,7 +36,6 @@
  */
 final class HfpClientProfile implements LocalBluetoothProfile {
     private static final String TAG = "HfpClientProfile";
-    private static boolean V = false;
 
     private BluetoothHeadsetClient mService;
     private boolean mIsProfileReady;
@@ -60,7 +59,7 @@
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (V) Log.d(TAG,"Bluetooth service connected");
+            Log.d(TAG, "Bluetooth service connected");
             mService = (BluetoothHeadsetClient) proxy;
             // We just bound to the service, so refresh the UI for any connected HFP devices.
             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -81,7 +80,7 @@
 
         @Override
         public void onServiceDisconnected(int profile) {
-            if (V) Log.d(TAG,"Bluetooth service disconnected");
+            Log.d(TAG, "Bluetooth service disconnected");
             mIsProfileReady=false;
         }
     }
@@ -115,7 +114,9 @@
     }
 
     public List<BluetoothDevice> getConnectedDevices() {
-        if (mService == null) return new ArrayList<BluetoothDevice>(0);
+        if (mService == null) {
+            return new ArrayList<BluetoothDevice>(0);
+        }
         return mService.getDevicesMatchingConnectionStates(
               new int[] {BluetoothProfile.STATE_CONNECTED,
                          BluetoothProfile.STATE_CONNECTING,
@@ -124,23 +125,17 @@
 
     @Override
     public boolean connect(BluetoothDevice device) {
-        if (mService == null) return false;
-        List<BluetoothDevice> srcs = getConnectedDevices();
-        if (srcs != null) {
-            for (BluetoothDevice src : srcs) {
-                if (src.equals(device)) {
-                    // Connect to same device, Ignore it
-                    Log.d(TAG,"Ignoring Connect");
-                    return true;
-                }
-            }
+        if (mService == null) {
+            return false;
         }
         return mService.connect(device);
     }
 
     @Override
     public boolean disconnect(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         // Downgrade priority as user is disconnecting the headset.
         if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
             mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -158,19 +153,25 @@
 
     @Override
     public boolean isPreferred(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
     }
 
     @Override
     public int getPreferred(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+        if (mService == null) {
+            return BluetoothProfile.PRIORITY_OFF;
+        }
         return mService.getPriority(device);
     }
 
     @Override
     public void setPreferred(BluetoothDevice device, boolean preferred) {
-        if (mService == null) return;
+        if (mService == null) {
+            return;
+        }
         if (preferred) {
             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -216,7 +217,7 @@
     }
 
     protected void finalize() {
-        if (V) Log.d(TAG, "finalize()");
+        Log.d(TAG, "finalize()");
         if (mService != null) {
             try {
                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
diff --git a/packages/SettingsLib/tests/robotests/config/robolectric.properties b/packages/SettingsLib/tests/robotests/config/robolectric.properties
index 34a2a1a..6b5b8e5 100644
--- a/packages/SettingsLib/tests/robotests/config/robolectric.properties
+++ b/packages/SettingsLib/tests/robotests/config/robolectric.properties
@@ -1,2 +1,5 @@
 manifest=frameworks/base/packages/SettingsLib/tests/robotests/AndroidManifest.xml
-sdk=NEWEST_SDK
\ No newline at end of file
+sdk=NEWEST_SDK
+
+shadows=\
+   com.android.settingslib.testutils.shadow.ShadowXmlUtils
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java
new file mode 100644
index 0000000..274fff8
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothA2dpSink;
+import android.bluetooth.BluetoothProfile;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
+public class A2dpSinkProfileTest {
+
+    @Mock
+    private CachedBluetoothDeviceManager mDeviceManager;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private BluetoothA2dpSink mService;
+    @Mock
+    private CachedBluetoothDevice mCachedBluetoothDevice;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
+    private BluetoothProfile.ServiceListener mServiceListener;
+    private A2dpSinkProfile mProfile;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        mProfile = new A2dpSinkProfile(RuntimeEnvironment.application,
+                mDeviceManager, mProfileManager);
+        mServiceListener = mShadowBluetoothAdapter.getServiceListener();
+        mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK, mService);
+    }
+
+    @Test
+    public void connect_shouldConnectBluetoothA2dpSink() {
+        mProfile.connect(mBluetoothDevice);
+        verify(mService).connect(mBluetoothDevice);
+    }
+
+    @Test
+    public void disconnect_shouldDisconnectBluetoothA2dpSink() {
+        mProfile.disconnect(mBluetoothDevice);
+        verify(mService).disconnect(mBluetoothDevice);
+    }
+
+    @Test
+    public void getConnectionStatus_shouldReturnConnectionState() {
+        when(mService.getConnectionState(mBluetoothDevice)).
+                thenReturn(BluetoothProfile.STATE_CONNECTED);
+        assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+                isEqualTo(BluetoothProfile.STATE_CONNECTED);
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java
new file mode 100644
index 0000000..187be0b
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadsetClient;
+import android.bluetooth.BluetoothProfile;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
+public class HfpClientProfileTest {
+
+    @Mock
+    private CachedBluetoothDeviceManager mDeviceManager;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private BluetoothHeadsetClient mService;
+    @Mock
+    private CachedBluetoothDevice mCachedBluetoothDevice;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
+    private BluetoothProfile.ServiceListener mServiceListener;
+    private HfpClientProfile mProfile;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        mProfile = new HfpClientProfile(RuntimeEnvironment.application,
+                mDeviceManager, mProfileManager);
+        mServiceListener = mShadowBluetoothAdapter.getServiceListener();
+        mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT, mService);
+    }
+
+    @Test
+    public void connect_shouldConnectBluetoothHeadsetClient() {
+        mProfile.connect(mBluetoothDevice);
+        verify(mService).connect(mBluetoothDevice);
+    }
+
+    @Test
+    public void disconnect_shouldDisconnectBluetoothHeadsetClient() {
+        mProfile.disconnect(mBluetoothDevice);
+        verify(mService).disconnect(mBluetoothDevice);
+    }
+
+    @Test
+    public void getConnectionStatus_shouldReturnConnectionState() {
+        when(mService.getConnectionState(mBluetoothDevice)).
+                thenReturn(BluetoothProfile.STATE_CONNECTED);
+        assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+                isEqualTo(BluetoothProfile.STATE_CONNECTED);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowXmlUtils.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowXmlUtils.java
new file mode 100644
index 0000000..3455765
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowXmlUtils.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.testutils.shadow;
+
+import static org.robolectric.shadow.api.Shadow.directlyOn;
+
+import com.android.internal.util.XmlUtils;
+
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.util.ReflectionHelpers;
+
+@Implements(XmlUtils.class)
+public class ShadowXmlUtils {
+
+    @Implementation
+    public static final int convertValueToInt(CharSequence charSeq, int defaultValue) {
+        final Class<?> xmlUtilsClass = ReflectionHelpers.loadClass(
+                Robolectric.class.getClassLoader(), "com.android.internal.util.XmlUtils");
+        try {
+            return directlyOn(xmlUtilsClass, "convertValueToInt",
+                    ReflectionHelpers.ClassParameter.from(CharSequence.class, charSeq),
+                    ReflectionHelpers.ClassParameter.from(int.class, new Integer(defaultValue)));
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 4fc190d..ec35b3d 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -16,6 +16,8 @@
 
 package com.android.shell;
 
+import static android.content.pm.PackageManager.FEATURE_LEANBACK;
+import static android.content.pm.PackageManager.FEATURE_TELEVISION;
 import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
 
 import static com.android.shell.BugreportPrefs.STATE_HIDE;
@@ -235,6 +237,7 @@
     private static final Bundle sNotificationBundle = new Bundle();
 
     private boolean mIsWatch;
+    private boolean mIsTv;
 
     private int mLastProgressPercent;
 
@@ -255,6 +258,9 @@
         final Configuration conf = mContext.getResources().getConfiguration();
         mIsWatch = (conf.uiMode & Configuration.UI_MODE_TYPE_MASK) ==
                 Configuration.UI_MODE_TYPE_WATCH;
+        PackageManager packageManager = getPackageManager();
+        mIsTv = packageManager.hasSystemFeature(FEATURE_LEANBACK)
+                || packageManager.hasSystemFeature(FEATURE_TELEVISION);
         NotificationManager nm = NotificationManager.from(mContext);
         nm.createNotificationChannel(
                 new NotificationChannel(NOTIFICATION_CHANNEL_ID,
@@ -500,8 +506,8 @@
                 .setProgress(info.max, info.progress, false)
                 .setOngoing(true);
 
-        // Wear bugreport doesn't need the bug info dialog, screenshot and cancel action.
-        if (!mIsWatch) {
+        // Wear and ATV bugreport doesn't need the bug info dialog, screenshot and cancel action.
+        if (!(mIsWatch || mIsTv)) {
             final Action cancelAction = new Action.Builder(null, mContext.getString(
                     com.android.internal.R.string.cancel), newCancelIntent(mContext, info)).build();
             final Intent infoIntent = new Intent(mContext, BugreportProgressService.class);
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 0913503..9c33116 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -66,6 +66,7 @@
     libs: [
         "telephony-common",
         "android.car",
+        "android.car.user",
     ],
 
     aaptflags: [
@@ -119,6 +120,7 @@
         "android.test.runner",
         "telephony-common",
         "android.car",
+        "android.car.user",
         "android.test.base",
     ],
     aaptflags: [
@@ -144,6 +146,7 @@
     libs: [
         "telephony-common",
         "android.car",
+        "android.car.user",
     ],
 
     dxflags: ["--multi-dex"],
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 2cbb78a..3744105 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -356,10 +356,11 @@
     if (supplementalIconId != 0) {
       Drawable supplementalIcon = mContext.getResources().getDrawable(supplementalIconId);
       supplementalIcon.mutate().setTint(color);
-      listItem.setSupplementalIcon(supplementalIcon, true,
-          supplementalIconOnClickListener);
+      listItem.setSupplementalIcon(supplementalIcon, true);
+      listItem.setSupplementalIconListener(supplementalIconOnClickListener);
     } else {
       listItem.setSupplementalEmptyIcon(true);
+      listItem.setSupplementalIconListener(null);
     }
 
     mVolumeLineItems.add(listItem);
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 6057614..aac37a2 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -38,7 +38,8 @@
     android.test.runner \
     telephony-common \
     android.test.base \
-    android.car
+    android.car \
+    android.car.user
 
 LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui:com.android.keyguard
 
diff --git a/proto/src/metrics_constants/OWNERS b/proto/src/metrics_constants/OWNERS
new file mode 100644
index 0000000..7009282
--- /dev/null
+++ b/proto/src/metrics_constants/OWNERS
@@ -0,0 +1,4 @@
+cwren@android.com
+yanglu@google.com
+yaochen@google.com
+yro@google.com
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
similarity index 100%
rename from proto/src/metrics_constants.proto
rename to proto/src/metrics_constants/metrics_constants.proto
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index c612c88..8c8352f 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -378,7 +378,6 @@
         if (newSession == null) {
             return NO_SESSION;
         }
-        autofillId.setSessionId(newSession.id);
 
         final String historyItem =
                 "id=" + newSession.id + " uid=" + uid + " a=" + shortComponentName
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index a9257f6..c9eb2d2 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -23,7 +23,6 @@
 import static android.view.autofill.AutofillManager.ACTION_VALUE_CHANGED;
 import static android.view.autofill.AutofillManager.ACTION_VIEW_ENTERED;
 import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
-import static android.view.autofill.AutofillManager.NO_SESSION;
 
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 import static com.android.server.autofill.Helper.getNumericValue;
@@ -76,6 +75,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.LocalLog;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -128,7 +128,7 @@
 
     private final MetricsLogger mMetricsLogger = new MetricsLogger();
 
-    private static AtomicInteger sIdCounter = new AtomicInteger(1);
+    private static AtomicInteger sIdCounter = new AtomicInteger();
 
     /** ID of the session */
     public final int id;
@@ -385,7 +385,6 @@
 
     @Override
     public AutofillValue findRawValueByAutofillId(AutofillId id) {
-        if (id == null) return null;
         synchronized (mLock) {
             return findValueLocked(id);
         }
@@ -398,50 +397,39 @@
     @GuardedBy("mLock")
     @Nullable
     private AutofillValue findValueLocked(@NonNull AutofillId autofillId) {
-        // TODO(b/113281366): rather than explicitly look for previous session, it might be
-        // better to merge the sessions when created (see note on mergePreviousSessionLocked())
-        final int requiredId = autofillId.getSessionId();
-        Session rightSession = null;
-        if (requiredId == NO_SESSION || requiredId == id) {
-            rightSession = this;
-        } else {
-            final ArrayList<Session> previousSessions = mService.getPreviousSessionsLocked(this);
-            if (previousSessions == null) {
-                if (sVerbose) Slog.v(TAG, "findValue(): no previous sessions");
-                return null;
-            }
+        final AutofillValue value = findValueFromThisSessionOnlyLocked(autofillId);
+        if (value != null) return value;
+
+        // TODO(b/113281366): rather than explicitly look for previous session, it might be better
+        // to merge the sessions when created (see note on mergePreviousSessionLocked())
+        final ArrayList<Session> previousSessions = mService.getPreviousSessionsLocked(this);
+        if (previousSessions != null) {
             if (sDebug) {
-                Slog.d(TAG, "findValue(): looking on " + previousSessions.size()
+                Slog.d(TAG, "findValueLocked(): looking on " + previousSessions.size()
                         + " previous sessions for autofillId " + autofillId);
             }
             for (int i = 0; i < previousSessions.size(); i++) {
                 final Session previousSession = previousSessions.get(i);
-                if (previousSession.id == requiredId) {
-                    rightSession = previousSession;
-                    break;
+                final AutofillValue previousValue = previousSession
+                        .findValueFromThisSessionOnlyLocked(autofillId);
+                if (previousValue != null) {
+                    return previousValue;
                 }
             }
         }
-        if (rightSession == null) {
-            Slog.w(TAG, "findValue(): no session with id" + requiredId);
-            return null;
-        }
-        return rightSession.findValueFromThisSessionOnlyLocked(autofillId);
+        return null;
     }
 
-    @GuardedBy("mLock")
     @Nullable
     private AutofillValue findValueFromThisSessionOnlyLocked(@NonNull AutofillId autofillId) {
         final ViewState state = mViewStates.get(autofillId);
         if (state == null) {
-            if (sDebug) {
-                Slog.d(TAG, "findValueLocked(): no view state for " + autofillId + " on " + id);
-            }
+            if (sDebug) Slog.d(TAG, "findValueLocked(): no view state for " + autofillId);
             return null;
         }
         AutofillValue value = state.getCurrentValue();
         if (value == null) {
-            Slog.d(TAG, "findValueLocked(): no current value for " + autofillId + " on " + id);
+            if (sDebug) Slog.d(TAG, "findValueLocked(): no current value for " + autofillId);
             value = getValueFromContextsLocked(autofillId);
         }
         return value;
diff --git a/services/backup/java/com/android/server/backup/encryption/chunk/ChunkHash.java b/services/backup/java/com/android/server/backup/encryption/chunk/ChunkHash.java
new file mode 100644
index 0000000..1ae598e
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunk/ChunkHash.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.encryption.chunk;
+
+import com.android.internal.util.Preconditions;
+import java.util.Arrays;
+import java.util.Base64;
+
+/**
+ * Represents the SHA-256 hash of the plaintext of a chunk, which is frequently used as a key.
+ *
+ * <p>This class is {@link Comparable} and implements {@link #equals(Object)} and {@link
+ * #hashCode()}.
+ */
+public class ChunkHash implements Comparable<ChunkHash> {
+    /** The length of the hash in bytes. The hash is a SHA-256, so this is 256 bits. */
+    public static final int HASH_LENGTH_BYTES = 256 / 8;
+
+    private static final int UNSIGNED_MASK = 0xFF;
+
+    private final byte[] mHash;
+
+    /** Constructs a new instance which wraps the given SHA-256 hash bytes. */
+    public ChunkHash(byte[] hash) {
+        Preconditions.checkArgument(hash.length == HASH_LENGTH_BYTES, "Hash must have 256 bits");
+        mHash = hash;
+    }
+
+    public byte[] getHash() {
+        return mHash;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof ChunkHash)) {
+            return false;
+        }
+
+        ChunkHash chunkHash = (ChunkHash) o;
+        return Arrays.equals(mHash, chunkHash.mHash);
+    }
+
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(mHash);
+    }
+
+    @Override
+    public int compareTo(ChunkHash other) {
+        return lexicographicalCompareUnsignedBytes(getHash(), other.getHash());
+    }
+
+    @Override
+    public String toString() {
+        return Base64.getEncoder().encodeToString(mHash);
+    }
+
+    private static int lexicographicalCompareUnsignedBytes(byte[] left, byte[] right) {
+        int minLength = Math.min(left.length, right.length);
+        for (int i = 0; i < minLength; i++) {
+            int result = toInt(left[i]) - toInt(right[i]);
+            if (result != 0) {
+                return result;
+            }
+        }
+        return left.length - right.length;
+    }
+
+    private static int toInt(byte value) {
+        return value & UNSIGNED_MASK;
+    }
+}
diff --git a/services/core/java/com/android/server/HardwarePropertiesManagerService.java b/services/core/java/com/android/server/HardwarePropertiesManagerService.java
index 4016d29..e21a3d7 100644
--- a/services/core/java/com/android/server/HardwarePropertiesManagerService.java
+++ b/services/core/java/com/android/server/HardwarePropertiesManagerService.java
@@ -26,7 +26,6 @@
 import static android.os.HardwarePropertiesManager.TEMPERATURE_THROTTLING_BELOW_VR_MIN;
 
 import android.Manifest;
-import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
@@ -34,8 +33,8 @@
 import android.os.Binder;
 import android.os.CpuUsageInfo;
 import android.os.IHardwarePropertiesManager;
-import android.os.Process;
 import android.os.UserHandle;
+
 import com.android.internal.util.DumpUtils;
 import com.android.server.vr.VrManagerInternal;
 
@@ -166,11 +165,11 @@
         final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
         final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
         if (!dpm.isDeviceOwnerApp(callingPackage)
-                && !vrService.isCurrentVrListener(callingPackage, userId)
                 && mContext.checkCallingOrSelfPermission(Manifest.permission.DEVICE_POWER)
-                        != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("The caller is not a device owner, bound VrListenerService"
-                + ", or holding the DEVICE_POWER permission.");
+                        != PackageManager.PERMISSION_GRANTED
+                && (vrService == null || !vrService.isCurrentVrListener(callingPackage, userId))) {
+            throw new SecurityException("The caller is neither a device owner"
+                + ", nor holding the DEVICE_POWER permission, nor the current VrListener.");
         }
     }
 }
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 40f81b3..708350d 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -20,7 +20,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
-import com.android.internal.inputmethod.InputMethodUtils;
+import com.android.internal.inputmethod.LocaleUtils;
 import com.android.internal.textservice.ISpellCheckerService;
 import com.android.internal.textservice.ISpellCheckerServiceCallback;
 import com.android.internal.textservice.ISpellCheckerSession;
@@ -461,7 +461,7 @@
         // is pre-installed or not.
         final Locale systemLocal = mContext.getResources().getConfiguration().locale;
         final ArrayList<Locale> suitableLocales =
-                InputMethodUtils.getSuitableLocalesForSpellChecker(systemLocal);
+                LocaleUtils.getSuitableLocalesForSpellChecker(systemLocal);
         if (DBG) {
             Slog.w(TAG, "findAvailSystemSpellCheckerLocked suitableLocales="
                     + Arrays.toString(suitableLocales.toArray(new Locale[suitableLocales.size()])));
@@ -475,7 +475,7 @@
                 final int subtypeCount = info.getSubtypeCount();
                 for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) {
                     final SpellCheckerSubtype subtype = info.getSubtypeAt(subtypeIndex);
-                    final Locale subtypeLocale = InputMethodUtils.constructLocaleFromString(
+                    final Locale subtypeLocale = LocaleUtils.constructLocaleFromString(
                             subtype.getLocale());
                     if (locale.equals(subtypeLocale)) {
                         // TODO: We may have more spell checkers that fall into this category.
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index fd32b5a..a392b51 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1185,8 +1185,8 @@
                         final long accountId = accountEntry.getKey();
                         final Account account = accountEntry.getValue();
                         if (obsoleteAuthType.contains(account.type)) {
-                            Slog.w(TAG, "deleting account " + account.name + " because type "
-                                    + account.type
+                            Slog.w(TAG, "deleting account " + account.toSafeString()
+                                    + " because type " + account.type
                                     + "'s registered authenticator no longer exist.");
                             Map<String, Integer> packagesToVisibility =
                                     getRequestingPackages(account, accounts);
@@ -1326,7 +1326,8 @@
         Preconditions.checkState(Thread.holdsLock(mUsers), "mUsers lock must be held");
         List<Account> accountsToRemove = accounts.accountsDb.findCeAccountsNotInDe();
         if (!accountsToRemove.isEmpty()) {
-            Slog.i(TAG, "Accounts " + accountsToRemove + " were previously deleted while user "
+            Slog.i(TAG, accountsToRemove.size()
+                    + " accounts were previously deleted while user "
                     + accounts.userId + " was locked. Removing accounts from CE tables");
             logRecord(accounts, AccountsDb.DEBUG_ACTION_SYNC_DE_CE_ACCOUNTS,
                     AccountsDb.TABLE_ACCOUNTS);
@@ -1641,7 +1642,7 @@
             return;
         }
 
-        Slog.d(TAG, "Copying account " + account.name
+        Slog.d(TAG, "Copying account " + account.toSafeString()
                 + " from user " + userFrom + " to user " + userTo);
         long identityToken = clearCallingIdentity();
         try {
@@ -1777,8 +1778,8 @@
             return false;
         }
         if (!isLocalUnlockedUser(accounts.userId)) {
-            Log.w(TAG, "Account " + account + " cannot be added - user " + accounts.userId
-                    + " is locked. callingUid=" + callingUid);
+            Log.w(TAG, "Account " + account.toSafeString() + " cannot be added - user "
+                    + accounts.userId + " is locked. callingUid=" + callingUid);
             return false;
         }
         synchronized (accounts.dbLock) {
@@ -1786,19 +1787,19 @@
                 accounts.accountsDb.beginTransaction();
                 try {
                     if (accounts.accountsDb.findCeAccountId(account) >= 0) {
-                        Log.w(TAG, "insertAccountIntoDatabase: " + account
+                        Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString()
                                 + ", skipping since the account already exists");
                         return false;
                     }
                     long accountId = accounts.accountsDb.insertCeAccount(account, password);
                     if (accountId < 0) {
-                        Log.w(TAG, "insertAccountIntoDatabase: " + account
+                        Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString()
                                 + ", skipping the DB insert failed");
                         return false;
                     }
                     // Insert into DE table
                     if (accounts.accountsDb.insertDeAccount(account, accountId) < 0) {
-                        Log.w(TAG, "insertAccountIntoDatabase: " + account
+                        Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString()
                                 + ", skipping the DB insert failed");
                         return false;
                     }
@@ -1806,7 +1807,8 @@
                         for (String key : extras.keySet()) {
                             final String value = extras.getString(key);
                             if (accounts.accountsDb.insertExtra(accountId, key, value) < 0) {
-                                Log.w(TAG, "insertAccountIntoDatabase: " + account
+                                Log.w(TAG, "insertAccountIntoDatabase: "
+                                        + account.toSafeString()
                                         + ", skipping since insertExtra failed for key " + key);
                                 return false;
                             }
@@ -2282,7 +2284,8 @@
         boolean isChanged = false;
         boolean userUnlocked = isLocalUnlockedUser(accounts.userId);
         if (!userUnlocked) {
-            Slog.i(TAG, "Removing account " + account + " while user "+ accounts.userId
+            Slog.i(TAG, "Removing account " + account.toSafeString()
+                    + " while user " + accounts.userId
                     + " is still locked. CE data will be removed later");
         }
         synchronized (accounts.dbLock) {
@@ -2907,7 +2910,7 @@
                 protected String toDebugString(long now) {
                     if (loginOptions != null) loginOptions.keySet();
                     return super.toDebugString(now) + ", getAuthToken"
-                            + ", " + account
+                            + ", " + account.toSafeString()
                             + ", authTokenType " + authTokenType
                             + ", loginOptions " + loginOptions
                             + ", notifyOnAuthFailure " + notifyOnAuthFailure;
@@ -3669,7 +3672,7 @@
                 @Override
                 protected String toDebugString(long now) {
                     return super.toDebugString(now) + ", confirmCredentials"
-                            + ", " + account;
+                            + ", " + account.toSafeString();
                 }
             }.bind();
         } finally {
@@ -3707,7 +3710,7 @@
                 protected String toDebugString(long now) {
                     if (loginOptions != null) loginOptions.keySet();
                     return super.toDebugString(now) + ", updateCredentials"
-                            + ", " + account
+                            + ", " + account.toSafeString()
                             + ", authTokenType " + authTokenType
                             + ", loginOptions " + loginOptions;
                 }
@@ -3771,7 +3774,7 @@
                         loginOptions.keySet();
                     return super.toDebugString(now)
                             + ", startUpdateCredentialsSession"
-                            + ", " + account
+                            + ", " + account.toSafeString()
                             + ", authTokenType " + authTokenType
                             + ", loginOptions " + loginOptions;
                 }
@@ -3812,7 +3815,7 @@
                 @Override
                 protected String toDebugString(long now) {
                     return super.toDebugString(now) + ", isCredentialsUpdateSuggested"
-                            + ", " + account;
+                            + ", " + account.toSafeString();
                 }
 
                 @Override
@@ -4369,7 +4372,7 @@
         accounts.accountsDb.deleteSharedAccount(account);
         long accountId = accounts.accountsDb.insertSharedAccount(account);
         if (accountId < 0) {
-            Log.w(TAG, "insertAccountIntoDatabase: " + account
+            Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString()
                     + ", skipping the DB insert failed");
             return false;
         }
@@ -5208,7 +5211,7 @@
                     Process.SYSTEM_UID, null /* packageName */, false);
             fout.println("Accounts: " + accounts.length);
             for (Account account : accounts) {
-                fout.println("  " + account);
+                fout.println("  " + account.toSafeString());
             }
 
             // Add debug information.
@@ -5613,7 +5616,8 @@
                 if (!permissionGranted && ActivityManager.isRunningInTestHarness()) {
                     // TODO: Skip this check when running automated tests. Replace this
                     // with a more general solution.
-                    Log.d(TAG, "no credentials permission for usage of " + account + ", "
+                    Log.d(TAG, "no credentials permission for usage of "
+                            + account.toSafeString() + ", "
                             + authTokenType + " by uid " + callerUid
                             + " but ignoring since device is in test harness.");
                     return true;
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 7276222..1866420 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -296,7 +296,13 @@
     <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r,
             @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType,
             boolean onTop) {
-        final int windowingMode = resolveWindowingMode(r, options, candidateTask, activityType);
+        // First preference is the windowing mode in the activity options if set.
+        int windowingMode = (options != null)
+                ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
+        // Validate that our desired windowingMode will work under the current conditions.
+        // UNDEFINED windowing mode is a valid result and means that the new stack will inherit
+        // it's display's windowing mode.
+        windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
         return getOrCreateStack(windowingMode, activityType, onTop);
     }
 
@@ -308,7 +314,7 @@
      * Creates a stack matching the input windowing mode and activity type on this display.
      * @param windowingMode The windowing mode the stack should be created in. If
      *                      {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
-     *                      be created in {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}.
+     *                      inherit it's parent's windowing mode.
      * @param activityType The activityType the stack should be created in. If
      *                     {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
      *                     be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
@@ -589,7 +595,7 @@
                 if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
                     continue;
                 }
-                otherStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN, false /* animate */,
+                otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED, false /* animate */,
                         false /* showRecents */, false /* enteringSplitScreenMode */,
                         true /* deferEnsuringVisibility */);
             }
@@ -650,10 +656,14 @@
             return false;
         }
 
+        final int displayWindowingMode = getWindowingMode();
         if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
                 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
             return supportsSplitScreen
-                    && WindowConfiguration.supportSplitScreenWindowingMode(activityType);
+                    && WindowConfiguration.supportSplitScreenWindowingMode(activityType)
+                    // Freeform windows and split-screen windows don't mix well, so prevent
+                    // split windowing modes on freeform displays.
+                    && displayWindowingMode != WINDOWING_MODE_FREEFORM;
         }
 
         if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
@@ -666,6 +676,16 @@
         return true;
     }
 
+    /**
+     * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
+     * display with the provided parameters.
+     *
+     * @param r The ActivityRecord in question.
+     * @param options Options to start with.
+     * @param task The task within-which the activity would start.
+     * @param activityType The type of activity to start.
+     * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
+     */
     int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
             @Nullable TaskRecord task, int activityType) {
 
@@ -687,7 +707,9 @@
                 windowingMode = getWindowingMode();
             }
         }
-        return validateWindowingMode(windowingMode, r, task, activityType);
+        windowingMode = validateWindowingMode(windowingMode, r, task, activityType);
+        return windowingMode != WINDOWING_MODE_UNDEFINED
+                ? windowingMode : WINDOWING_MODE_FULLSCREEN;
     }
 
     /**
@@ -724,23 +746,21 @@
         final boolean inSplitScreenMode = hasSplitScreenPrimaryStack();
         if (!inSplitScreenMode
                 && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
-            // Switch to fullscreen windowing mode if we are not in split-screen mode and we are
+            // Switch to the display's windowing mode if we are not in split-screen mode and we are
             // trying to launch in split-screen secondary.
-            windowingMode = WINDOWING_MODE_FULLSCREEN;
-        } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN
+            windowingMode = WINDOWING_MODE_UNDEFINED;
+        } else if (inSplitScreenMode && (windowingMode == WINDOWING_MODE_FULLSCREEN
+                        || windowingMode == WINDOWING_MODE_UNDEFINED)
                 && supportsSplitScreen) {
             windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
         }
 
         if (windowingMode != WINDOWING_MODE_UNDEFINED
                 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
-                supportsFreeform, supportsPip, activityType)) {
+                        supportsFreeform, supportsPip, activityType)) {
             return windowingMode;
         }
-        // Try to use the display's windowing mode otherwise fallback to fullscreen.
-        windowingMode = getWindowingMode();
-        return windowingMode != WINDOWING_MODE_UNDEFINED
-                ? windowingMode : WINDOWING_MODE_FULLSCREEN;
+        return WINDOWING_MODE_UNDEFINED;
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2ee598f..c721901 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2382,7 +2382,7 @@
                 }
             }
             int logSampleRate = Settings.Global.getInt(mContext.getContentResolver(),
-                    Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE, -1);
+                    Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE, 0x200);
             if (logSampleRate < 0 || logSampleRate > 0x10000) {
                 logSampleRate = -1;
             }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index bc99827..aa4e68d 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -347,6 +347,9 @@
     /** The attached Display's unique identifier, or -1 if detached */
     int mDisplayId;
 
+    /** Stores the override windowing-mode from before a transient mode change (eg. split) */
+    private int mRestoreOverrideWindowingMode = WINDOWING_MODE_UNDEFINED;
+
     private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
     private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>();
     private final Rect mTmpRect2 = new Rect();
@@ -531,16 +534,48 @@
                 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */);
     }
 
+    /**
+     * A transient windowing mode is one which activities enter into temporarily. Examples of this
+     * are Split window modes and pip. Non-transient modes are modes that displays can adopt.
+     *
+     * @param windowingMode the windowingMode to test for transient-ness.
+     * @return {@code true} if the windowing mode is transient, {@code false} otherwise.
+     */
+    private static boolean isTransientWindowingMode(int windowingMode) {
+        // TODO(b/114842032): add PIP if/when it uses mode transitions instead of task reparenting
+        return windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+                || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+    }
+
+    /**
+     * Specialization of {@link #setWindowingMode(int)} for this subclass.
+     *
+     * @param preferredWindowingMode the preferred windowing mode. This may not be honored depending
+     *         on the state of things. For example, WINDOWING_MODE_UNDEFINED will resolve to the
+     *         previous non-transient mode if this stack is currently in a transient mode.
+     * @param animate Can be used to prevent animation.
+     * @param showRecents Controls whether recents is shown on the other side of a split while
+     *         entering split mode.
+     * @param enteringSplitScreenMode {@code true} if entering split mode.
+     * @param deferEnsuringVisibility Whether visibility updates are deferred. This is set when
+     *         many operations (which can effect visibility) are being performed in bulk.
+     */
     void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents,
             boolean enteringSplitScreenMode, boolean deferEnsuringVisibility) {
         final boolean creating = mWindowContainerController == null;
         final int currentMode = getWindowingMode();
+        final int currentOverrideMode = getOverrideWindowingMode();
         final ActivityDisplay display = getDisplay();
         final TaskRecord topTask = topTask();
         final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack();
-        mTmpOptions.setLaunchWindowingMode(preferredWindowingMode);
-
         int windowingMode = preferredWindowingMode;
+        if (preferredWindowingMode == WINDOWING_MODE_UNDEFINED
+                && isTransientWindowingMode(currentMode)) {
+            // Leaving a transient mode. Interpret UNDEFINED as "restore"
+            windowingMode = mRestoreOverrideWindowingMode;
+        }
+        mTmpOptions.setLaunchWindowingMode(windowingMode);
+
         // Need to make sure windowing mode is supported. If we in the process of creating the stack
         // no need to resolve the windowing mode again as it is already resolved to the right mode.
         if (!creating) {
@@ -550,8 +585,8 @@
         if (splitScreenStack == this
                 && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
             // Resolution to split-screen secondary for the primary split-screen stack means
-            // we want to go fullscreen.
-            windowingMode = WINDOWING_MODE_FULLSCREEN;
+            // we want to leave split-screen mode.
+            windowingMode = mRestoreOverrideWindowingMode;
         }
 
         final boolean alreadyInSplitScreenMode = display.hasSplitScreenPrimaryStack();
@@ -570,21 +605,33 @@
                 // doesn't support split-screen mode, go ahead an dismiss split-screen and display a
                 // warning toast about it.
                 mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
-                display.getSplitScreenPrimaryStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN,
+                display.getSplitScreenPrimaryStack().setWindowingMode(WINDOWING_MODE_UNDEFINED,
                         false /* animate */, false /* showRecents */,
                         false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */);
             }
         }
 
         if (currentMode == windowingMode) {
-            // You are already in the window mode silly...
+            // You are already in the window mode, so we can skip most of the work below. However,
+            // it's possible that we have inherited the current windowing mode from a parent. So,
+            // fulfill this method's contract by setting the override mode directly.
+            getOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
             return;
         }
 
         final WindowManagerService wm = mService.mWindowManager;
         final ActivityRecord topActivity = getTopActivity();
 
-        if (sendNonResizeableNotification && windowingMode != WINDOWING_MODE_FULLSCREEN
+        // For now, assume that the Stack's windowing mode is what will actually be used
+        // by it's activities. In the future, there may be situations where this doesn't
+        // happen; so at that point, this message will need to handle that.
+        int likelyResolvedMode = windowingMode;
+        if (windowingMode == WINDOWING_MODE_UNDEFINED) {
+            final ConfigurationContainer parent = getParent();
+            likelyResolvedMode = parent != null ? parent.getWindowingMode()
+                    : WINDOWING_MODE_FULLSCREEN;
+        }
+        if (sendNonResizeableNotification && likelyResolvedMode != WINDOWING_MODE_FULLSCREEN
                 && topActivity != null && topActivity.isNonResizableOrForcedResizable()
                 && !topActivity.noDisplay) {
             // Inform the user that they are starting an app that may not work correctly in
@@ -625,6 +672,9 @@
                         + " while there is already one isn't currently supported");
                 //return;
             }
+            if (isTransientWindowingMode(windowingMode) && !isTransientWindowingMode(currentMode)) {
+                mRestoreOverrideWindowingMode = currentOverrideMode;
+            }
 
             mTmpRect2.setEmpty();
             if (windowingMode != WINDOWING_MODE_FULLSCREEN) {
@@ -674,13 +724,6 @@
             // display, so they should be considered compatible.
             activityType = ACTIVITY_TYPE_STANDARD;
         }
-        final ActivityDisplay display = getDisplay();
-        if (display != null && activityType == ACTIVITY_TYPE_STANDARD
-                    && windowingMode == WINDOWING_MODE_UNDEFINED) {
-            // Standard activity types will mostly take on the windowing mode of the display if one
-            // isn't specified, so look-up a compatible stack based on the display's windowing mode.
-            windowingMode = display.getWindowingMode();
-        }
         return super.isCompatible(windowingMode, activityType);
     }
 
@@ -1085,7 +1128,7 @@
          * behind the home stack. Exit split screen in this case.
          */
         if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-            setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+            setWindowingMode(WINDOWING_MODE_UNDEFINED);
         }
 
         getDisplay().positionChildAtBottom(this);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index af2d3b0..310898e 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2828,8 +2828,7 @@
                     if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
                         continue;
                     }
-                    resizeStackLocked(otherStack, null, null, null, PRESERVE_WINDOWS,
-                            true /* allowResizeInDockedMode */, DEFER_RESUME);
+                    otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
                 }
 
                 // Also disable docked stack resizing since we have manually adjusted the
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 7eadcb3..212844a 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -3338,7 +3338,7 @@
                     }
                 }
 
-                stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+                stack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java
index 347a357..cd4d6a3 100644
--- a/services/core/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/core/java/com/android/server/am/BaseErrorDialog.java
@@ -33,7 +33,7 @@
     private boolean mConsuming = true;
 
     public BaseErrorDialog(Context context) {
-        super(context, com.android.internal.R.style.Theme_Dialog_AppError);
+        super(context, com.android.internal.R.style.Theme_DeviceDefault_Dialog_AppError);
         context.assertRuntimeOverlayThemable();
 
         getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 1b688a6..76c191d 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -26,8 +26,8 @@
 import android.util.Slog;
 import android.util.Spline;
 
-import com.android.internal.util.Preconditions;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
 import com.android.server.display.utils.Plog;
 
 import java.io.PrintWriter;
@@ -77,8 +77,8 @@
                 Slog.w(TAG, "Screen brightness mapping does not cover whole range of available " +
                         "backlight values, autobrightness functionality may be impaired.");
             }
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-            builder.setCurve(luxLevels, brightnessLevelsNits);
+            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
+                    luxLevels, brightnessLevelsNits);
             return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange,
                     autoBrightnessAdjustmentMaxGamma);
         } else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) {
diff --git a/services/core/java/com/android/server/InputContentUriTokenHandler.java b/services/core/java/com/android/server/inputmethod/InputContentUriTokenHandler.java
similarity index 97%
rename from services/core/java/com/android/server/InputContentUriTokenHandler.java
rename to services/core/java/com/android/server/inputmethod/InputContentUriTokenHandler.java
index 6338b2f..845fca1 100644
--- a/services/core/java/com/android/server/InputContentUriTokenHandler.java
+++ b/services/core/java/com/android/server/inputmethod/InputContentUriTokenHandler.java
@@ -14,11 +14,10 @@
 ** limitations under the License.
 */
 
-package com.android.server;
+package com.android.server.inputmethod;
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
-import android.app.ActivityManager;
 import android.app.UriGrantsManager;
 import android.content.Intent;
 import android.net.Uri;
@@ -28,6 +27,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.inputmethod.IInputContentUriToken;
+import com.android.server.LocalServices;
 import com.android.server.uri.UriGrantsManagerInternal;
 
 final class InputContentUriTokenHandler extends IInputContentUriToken.Stub {
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
similarity index 98%
rename from services/core/java/com/android/server/InputMethodManagerService.java
rename to services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 93d023d..49f33e0 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -13,7 +13,7 @@
  * the License.
  */
 
-package com.android.server;
+package com.android.server.inputmethod;
 
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
@@ -149,7 +149,9 @@
 import com.android.internal.view.IInputSessionCallback;
 import com.android.internal.view.InputBindResult;
 import com.android.internal.view.InputMethodClient;
-import com.android.server.inputmethod.InputMethodManagerInternal;
+import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
 import com.android.server.statusbar.StatusBarManagerService;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -210,7 +212,6 @@
     static final int MSG_BIND_CLIENT = 3010;
     static final int MSG_SET_ACTIVE = 3020;
     static final int MSG_SET_INTERACTIVE = 3030;
-    static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 3040;
     static final int MSG_REPORT_FULLSCREEN_MODE = 3045;
 
     static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
@@ -254,7 +255,7 @@
      * the notification.
      */
     private static final String ACTION_SHOW_INPUT_METHOD_PICKER =
-            "com.android.server.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER";
+            "com.android.server.inputmethod.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER";
 
     /**
      * Debug flag for overriding runtime {@link SystemProperties}.
@@ -598,8 +599,6 @@
      */
     boolean mIsInteractive = true;
 
-    int mCurUserActionNotificationSequenceNumber = 0;
-
     int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
 
     /**
@@ -1822,7 +1821,7 @@
         }
         return new InputBindResult(InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION,
                 session.session, (session.channel != null ? session.channel.dup() : null),
-                mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
+                mCurId, mCurSeq);
     }
 
     @GuardedBy("mMethodMap")
@@ -1881,8 +1880,7 @@
                     requestClientSessionLocked(cs);
                     return new InputBindResult(
                             InputBindResult.ResultCode.SUCCESS_WAITING_IME_SESSION,
-                            null, null, mCurId, mCurSeq,
-                            mCurUserActionNotificationSequenceNumber);
+                            null, null, mCurId, mCurSeq);
                 } else if (SystemClock.uptimeMillis()
                         < (mLastBindTime+TIME_TO_RECONNECT)) {
                     // In this case we have connected to the service, but
@@ -1894,8 +1892,7 @@
                     // to see if we can get back in touch with the service.
                     return new InputBindResult(
                             InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING,
-                            null, null, mCurId, mCurSeq,
-                            mCurUserActionNotificationSequenceNumber);
+                            null, null, mCurId, mCurSeq);
                 } else {
                     EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
                             mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);
@@ -1917,8 +1914,7 @@
             // party code.
             return new InputBindResult(
                     InputBindResult.ResultCode.ERROR_SYSTEM_NOT_READY,
-                    null, null, mCurMethodId, mCurSeq,
-                    mCurUserActionNotificationSequenceNumber);
+                    null, null, mCurMethodId, mCurSeq);
         }
 
         InputMethodInfo info = mMethodMap.get(mCurMethodId);
@@ -1946,8 +1942,7 @@
             }
             return new InputBindResult(
                     InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING,
-                    null, null, mCurId, mCurSeq,
-                    mCurUserActionNotificationSequenceNumber);
+                    null, null, mCurId, mCurSeq);
         }
         mCurIntent = null;
         Slog.w(TAG, "Failure connecting to input method service: " + mCurIntent);
@@ -2754,7 +2749,7 @@
                     }
                     return new InputBindResult(
                             InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,
-                            null, null, null, -1, -1);
+                            null, null, null, -1);
                 }
                 mCurFocusedWindow = windowToken;
                 mCurFocusedWindowSoftInputMode = softInputMode;
@@ -3172,17 +3167,16 @@
         mWindowManagerInternal.clearLastInputMethodWindowForTransition();
     }
 
-    @Override
-    public void notifyUserAction(int sequenceNumber) {
+    @BinderThread
+    private void notifyUserAction(@NonNull IBinder token) {
         if (DEBUG) {
-            Slog.d(TAG, "Got the notification of a user action. sequenceNumber:" + sequenceNumber);
+            Slog.d(TAG, "Got the notification of a user action.");
         }
         synchronized (mMethodMap) {
-            if (mCurUserActionNotificationSequenceNumber != sequenceNumber) {
+            if (mCurToken != token) {
                 if (DEBUG) {
-                    Slog.d(TAG, "Ignoring the user action notification due to the sequence number "
-                            + "mismatch. expected:" + mCurUserActionNotificationSequenceNumber
-                            + " actual: " + sequenceNumber);
+                    Slog.d(TAG, "Ignoring the user action notification from IMEs that are no longer"
+                            + " active.");
                 }
                 return;
             }
@@ -3445,20 +3439,6 @@
             case MSG_START_VR_INPUT:
                 startVrInputMethodNoCheck((ComponentName) msg.obj);
                 return true;
-            case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: {
-                final int sequenceNumber = msg.arg1;
-                final ClientState clientState = (ClientState)msg.obj;
-                try {
-                    clientState.client.setUserActionNotificationSequenceNumber(sequenceNumber);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Got RemoteException sending "
-                            + "setUserActionNotificationSequenceNumber("
-                            + sequenceNumber + ") notification to pid "
-                            + clientState.pid + " uid "
-                            + clientState.uid);
-                }
-                return true;
-            }
             case MSG_REPORT_FULLSCREEN_MODE: {
                 final boolean fullscreen = msg.arg1 != 0;
                 final ClientState clientState = (ClientState)msg.obj;
@@ -3944,19 +3924,6 @@
             mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype);
         }
 
-        mCurUserActionNotificationSequenceNumber =
-                Math.max(mCurUserActionNotificationSequenceNumber + 1, 1);
-        if (DEBUG) {
-            Slog.d(TAG, "Bump mCurUserActionNotificationSequenceNumber:"
-                    + mCurUserActionNotificationSequenceNumber);
-        }
-
-        if (mCurClient != null && mCurClient.client != null) {
-            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
-                    MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER,
-                    mCurUserActionNotificationSequenceNumber, mCurClient));
-        }
-
         if (isVrInput) {
             // Updates to InputMethod are transient in VR mode. Any changes to Settings are skipped.
             return;
@@ -4558,8 +4525,6 @@
                     + " mShowForced=" + mShowForced
                     + " mInputShown=" + mInputShown);
             p.println("  mInFullscreenMode=" + mInFullscreenMode);
-            p.println("  mCurUserActionNotificationSequenceNumber="
-                    + mCurUserActionNotificationSequenceNumber);
             p.println("  mSystemReady=" + mSystemReady + " mInteractive=" + mIsInteractive);
             p.println("  mSettingsObserver=" + mSettingsObserver);
             p.println("  mSwitchingController:");
@@ -5057,5 +5022,11 @@
         public boolean shouldOfferSwitchingToNextInputMethod() {
             return mImms.shouldOfferSwitchingToNextInputMethod(mToken);
         }
+
+        @BinderThread
+        @Override
+        public void notifyUserActionAsync() {
+            mImms.notifyUserAction(mToken);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 340ae0a..7751f5f 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -694,7 +694,8 @@
 
             for (int userId : userIds) {
                 if (enabled) {
-                    if (isPackageOrComponentAllowed(component.toString(), userId)) {
+                    if (isPackageOrComponentAllowed(component.toString(), userId)
+                            || isPackageOrComponentAllowed(component.getPackageName(), userId)) {
                         registerServiceLocked(component, userId);
                     } else {
                         Slog.d(TAG, component + " no longer has permission to be bound");
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index f2ce63c..64553a8 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -29,6 +29,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.app.WindowConfiguration.activityTypeToString;
 import static android.app.WindowConfiguration.windowingModeToString;
+
 import static com.android.server.wm.ConfigurationContainerProto.FULL_CONFIGURATION;
 import static com.android.server.wm.ConfigurationContainerProto.MERGED_OVERRIDE_CONFIGURATION;
 import static com.android.server.wm.ConfigurationContainerProto.OVERRIDE_CONFIGURATION;
@@ -295,6 +296,10 @@
         return mFullConfiguration.windowConfiguration.getWindowingMode();
     }
 
+    public int getOverrideWindowingMode() {
+        return mOverrideConfiguration.windowConfiguration.getWindowingMode();
+    }
+
     /** Sets the windowing mode for the configuration container. */
     public void setWindowingMode(/*@WindowConfiguration.WindowingMode*/ int windowingMode) {
         mTmpConfig.setTo(getOverrideConfiguration());
@@ -513,7 +518,8 @@
         final String childPrefix = prefix + " ";
         pw.println(getName()
                 + " type=" + activityTypeToString(getActivityType())
-                + " mode=" + windowingModeToString(getWindowingMode()));
+                + " mode=" + windowingModeToString(getWindowingMode())
+                + " override-mode=" + windowingModeToString(getOverrideWindowingMode()));
         for (int i = getChildCount() - 1; i >= 0; --i) {
             final E cc = getChildAt(i);
             pw.print(childPrefix + "#" + i + " ");
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index df680f2..ac496a8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -356,8 +356,8 @@
     /**
      * Notifies WindowManagerService that the current IME window status is being changed.
      *
-     * <p>Only {@link com.android.server.InputMethodManagerService} is the expected and tested
-     * caller of this method.</p>
+     * <p>Only {@link com.android.server.inputmethod.InputMethodManagerService} is the expected and
+     * tested caller of this method.</p>
      *
      * @param imeToken token to track the active input method. Corresponding IME windows can be
      *                 identified by checking {@link android.view.WindowManager.LayoutParams#token}.
@@ -376,8 +376,8 @@
     /**
      * Notifies WindowManagerService that the current IME window status is being changed.
      *
-     * <p>Only {@link com.android.server.InputMethodManagerService} is the expected and tested
-     * caller of this method.</p>
+     * <p>Only {@link com.android.server.inputmethod.InputMethodManagerService} is the expected and
+     * tested caller of this method.</p>
      *
      * @param imeToken token to track the active input method. Corresponding IME windows can be
      *                 identified by checking {@link android.view.WindowManager.LayoutParams#token}.
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0b6a33f..c80b9d8 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -82,6 +82,7 @@
 import com.android.server.biometrics.fingerprint.FingerprintService;
 import com.android.server.hdmi.HdmiControlService;
 import com.android.server.input.InputManagerService;
+import com.android.server.inputmethod.InputMethodManagerService;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.lights.LightsService;
 import com.android.server.media.MediaResourceMonitorService;
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index ccc092d..0176dd4 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -228,6 +228,9 @@
     //       Encourages logging of any available arguments, and all call sites
     //       are necessarily logged identically.
     //
+    // NOTE: Log first because passed objects may or may not be thread-safe and
+    // once passed on to the callback they may be modified by another thread.
+    //
     // TODO: Find an lighter weight approach.
     private class LoggingCallbackWrapper extends Callback {
         private static final String PREFIX = "INVOKE ";
@@ -243,63 +246,63 @@
 
         @Override
         public void onPreDhcpAction() {
-            mCallback.onPreDhcpAction();
             log("onPreDhcpAction()");
+            mCallback.onPreDhcpAction();
         }
         @Override
         public void onPostDhcpAction() {
-            mCallback.onPostDhcpAction();
             log("onPostDhcpAction()");
+            mCallback.onPostDhcpAction();
         }
         @Override
         public void onNewDhcpResults(DhcpResults dhcpResults) {
-            mCallback.onNewDhcpResults(dhcpResults);
             log("onNewDhcpResults({" + dhcpResults + "})");
+            mCallback.onNewDhcpResults(dhcpResults);
         }
         @Override
         public void onProvisioningSuccess(LinkProperties newLp) {
-            mCallback.onProvisioningSuccess(newLp);
             log("onProvisioningSuccess({" + newLp + "})");
+            mCallback.onProvisioningSuccess(newLp);
         }
         @Override
         public void onProvisioningFailure(LinkProperties newLp) {
-            mCallback.onProvisioningFailure(newLp);
             log("onProvisioningFailure({" + newLp + "})");
+            mCallback.onProvisioningFailure(newLp);
         }
         @Override
         public void onLinkPropertiesChange(LinkProperties newLp) {
-            mCallback.onLinkPropertiesChange(newLp);
             log("onLinkPropertiesChange({" + newLp + "})");
+            mCallback.onLinkPropertiesChange(newLp);
         }
         @Override
         public void onReachabilityLost(String logMsg) {
-            mCallback.onReachabilityLost(logMsg);
             log("onReachabilityLost(" + logMsg + ")");
+            mCallback.onReachabilityLost(logMsg);
         }
         @Override
         public void onQuit() {
-            mCallback.onQuit();
             log("onQuit()");
+            mCallback.onQuit();
         }
         @Override
         public void installPacketFilter(byte[] filter) {
-            mCallback.installPacketFilter(filter);
             log("installPacketFilter(byte[" + filter.length + "])");
+            mCallback.installPacketFilter(filter);
         }
         @Override
         public void startReadPacketFilter() {
-            mCallback.startReadPacketFilter();
             log("startReadPacketFilter()");
+            mCallback.startReadPacketFilter();
         }
         @Override
         public void setFallbackMulticastFilter(boolean enabled) {
-            mCallback.setFallbackMulticastFilter(enabled);
             log("setFallbackMulticastFilter(" + enabled + ")");
+            mCallback.setFallbackMulticastFilter(enabled);
         }
         @Override
         public void setNeighborDiscoveryOffload(boolean enable) {
-            mCallback.setNeighborDiscoveryOffload(enable);
             log("setNeighborDiscoveryOffload(" + enable + ")");
+            mCallback.setNeighborDiscoveryOffload(enable);
         }
     }
 
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index 2691701..8b59771 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -75,6 +75,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     platform-robolectric-android-all-stubs \
     android-support-test \
+    guava \
     mockito-robolectric-prebuilt \
     platform-test-annotations \
     truth-prebuilt \
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
new file mode 100644
index 0000000..3b6e038
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.encryption.chunk;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.platform.test.annotations.Presubmit;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+import com.google.common.primitives.Bytes;
+import java.util.Arrays;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class ChunkHashTest {
+    private static final int HASH_LENGTH_BYTES = 256 / 8;
+    private static final byte[] TEST_HASH_1 = Arrays.copyOf(new byte[] {1}, HASH_LENGTH_BYTES);
+    private static final byte[] TEST_HASH_2 = Arrays.copyOf(new byte[] {2}, HASH_LENGTH_BYTES);
+
+    @Test
+    public void testGetHash_returnsHash() {
+        ChunkHash chunkHash = new ChunkHash(TEST_HASH_1);
+
+        byte[] hash = chunkHash.getHash();
+
+        assertThat(hash).asList().containsExactlyElementsIn(Bytes.asList(TEST_HASH_1)).inOrder();
+    }
+
+    @Test
+    public void testEquals() {
+        ChunkHash chunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash equalChunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash chunkHash2 = new ChunkHash(TEST_HASH_2);
+
+        assertThat(chunkHash1).isEqualTo(equalChunkHash1);
+        assertThat(chunkHash1).isNotEqualTo(chunkHash2);
+    }
+
+    @Test
+    public void testHashCode() {
+        ChunkHash chunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash equalChunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash chunkHash2 = new ChunkHash(TEST_HASH_2);
+
+        int hash1 = chunkHash1.hashCode();
+        int equalHash1 = equalChunkHash1.hashCode();
+        int hash2 = chunkHash2.hashCode();
+
+        assertThat(hash1).isEqualTo(equalHash1);
+        assertThat(hash1).isNotEqualTo(hash2);
+    }
+
+    @Test
+    public void testCompareTo_whenEqual_returnsZero() {
+        ChunkHash chunkHash = new ChunkHash(TEST_HASH_1);
+        ChunkHash equalChunkHash = new ChunkHash(TEST_HASH_1);
+
+        int result = chunkHash.compareTo(equalChunkHash);
+
+        assertThat(result).isEqualTo(0);
+    }
+
+    @Test
+    public void testCompareTo_whenArgumentGreater_returnsNegative() {
+        ChunkHash chunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash chunkHash2 = new ChunkHash(TEST_HASH_2);
+
+        int result = chunkHash1.compareTo(chunkHash2);
+
+        assertThat(result).isLessThan(0);
+    }
+
+    @Test
+    public void testCompareTo_whenArgumentSmaller_returnsPositive() {
+        ChunkHash chunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash chunkHash2 = new ChunkHash(TEST_HASH_2);
+
+        int result = chunkHash2.compareTo(chunkHash1);
+
+        assertThat(result).isGreaterThan(0);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 1023bc1..95f8fd1 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -24,6 +24,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
 import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
 import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
@@ -73,7 +74,7 @@
         mService = createActivityTaskManagerService();
         mSupervisor = mService.mStackSupervisor;
         mDefaultDisplay = mService.mStackSupervisor.getDefaultDisplay();
-        mStack = mDefaultDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+        mStack = mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
     }
@@ -140,7 +141,7 @@
     }
 
     @Test
-    public void testPrimarySplitScreenToFullscreenWhenMovedToBack() throws Exception {
+    public void testPrimarySplitScreenRestoresWhenMovedToBack() throws Exception {
         // Create primary splitscreen stack. This will create secondary stacks and places the
         // existing fullscreen stack on the bottom.
         final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
@@ -158,6 +159,60 @@
 
         // Ensure no longer in splitscreen.
         assertEquals(primarySplitScreen.getWindowingMode(), WINDOWING_MODE_FULLSCREEN);
+
+        // Ensure that the override mode is restored to undefined
+        assertEquals(primarySplitScreen.getOverrideWindowingMode(), WINDOWING_MODE_UNDEFINED);
+    }
+
+    @Test
+    public void testPrimarySplitScreenRestoresPreviousWhenMovedToBack() throws Exception {
+        // This time, start with a fullscreen activitystack
+        final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
+            WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
+        primarySplitScreen.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+
+        // Assert windowing mode.
+        assertEquals(primarySplitScreen.getWindowingMode(), WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+
+        // Move primary to back.
+        primarySplitScreen.moveToBack("testPrimarySplitScreenToFullscreenWhenMovedToBack",
+            null /* task */);
+
+        // Assert that stack is at the bottom.
+        assertEquals(mDefaultDisplay.getIndexOf(primarySplitScreen), 0);
+
+        // Ensure that the override mode is restored to what it was (fullscreen)
+        assertEquals(primarySplitScreen.getOverrideWindowingMode(), WINDOWING_MODE_FULLSCREEN);
+    }
+
+    @Test
+    public void testStackInheritsDisplayWindowingMode() throws Exception {
+        final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
+            WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
+        assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
+        assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+
+        mDefaultDisplay.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        assertEquals(WINDOWING_MODE_FREEFORM, primarySplitScreen.getWindowingMode());
+        assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+    }
+
+    @Test
+    public void testStackOverridesDisplayWindowingMode() throws Exception {
+        final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
+            WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
+        assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
+        assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+
+        primarySplitScreen.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        // setting windowing mode should still work even though resolved mode is already fullscreen
+        assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getOverrideWindowingMode());
+
+        mDefaultDisplay.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index aef5537..bb8e5c5 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -520,6 +520,9 @@
         private final ActivityStackSupervisor mSupervisor;
         TestActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
             super(supervisor, displayId);
+            // Normally this comes from display-properties as exposed by WM. Without that, just
+            // hard-code to FULLSCREEN for tests.
+            setWindowingMode(WINDOWING_MODE_FULLSCREEN);
             mSupervisor = supervisor;
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index e6ca03b..48dda01 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -152,8 +152,7 @@
         final float[] lux = { 0f, 1f };
         final float[] nits = { 0, PowerManager.BRIGHTNESS_ON };
 
-        BrightnessConfiguration config = new BrightnessConfiguration.Builder()
-                .setCurve(lux, nits)
+        BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
                 .build();
         strategy.setBrightnessConfiguration(config);
         assertNotEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/);
@@ -214,8 +213,7 @@
                 DISPLAY_RANGE_NITS[DISPLAY_RANGE_NITS.length - 1]
         };
 
-        BrightnessConfiguration config = new BrightnessConfiguration.Builder()
-                .setCurve(lux, nits)
+        BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
                 .build();
         strategy.setBrightnessConfiguration(config);
         assertEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 1d9e605..8ebfec4 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1589,12 +1589,14 @@
     }
 
     /**
-     * @return true if a valid subId else false
-     * @hide
+     * Checks if the supplied subscription ID is valid.
+     * Note: a valid subscription ID does not necessarily correspond to an active subscription.
+     *
+     * @param subscriptionId The subscription ID.
+     * @return true if the supplied subscriptionId is valid; false otherwise.
      */
-    @UnsupportedAppUsage
-    public static boolean isValidSubscriptionId(int subId) {
-        return subId > INVALID_SUBSCRIPTION_ID ;
+    public static boolean isValidSubscriptionId(int subscriptionId) {
+        return subscriptionId > INVALID_SUBSCRIPTION_ID;
     }
 
     /**
diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh
index 29bf74c..e50c70d 100755
--- a/tools/aosp/aosp_sha.sh
+++ b/tools/aosp/aosp_sha.sh
@@ -1,18 +1,24 @@
 #!/bin/bash
-LOCAL_DIR="$( dirname ${BASH_SOURCE} )"
+LOCAL_DIR="$( dirname "${BASH_SOURCE}" )"
 
-if git branch -vv | grep "^*" | grep "\[aosp/master" > /dev/null; then
+if git branch -vv | grep -q -P "^\*[^\[]+\[aosp/"; then
     # Change appears to be in AOSP
     exit 0
 else
     # Change appears to be non-AOSP; search for files
-    git show --name-only --pretty=format: $1 | grep $2 | while read file; do
-        echo
+    count=0
+    while read -r file ; do
+        if (( count == 0 )); then
+            echo
+        fi
         echo -e "\033[0;31mThe source of truth for '$file' is in AOSP.\033[0m"
+        (( count++ ))
+    done < <(git show --name-only --pretty=format: $1 | grep -- "$2")
+    if (( count != 0 )); then
         echo
-        echo "If your change contains no confidential details, please upload and merge"
-        echo "this change at https://android-review.googlesource.com/."
+        echo "If your change contains no confidential details (such as security fixes), please"
+        echo "upload and merge this change at https://android-review.googlesource.com/."
         echo
         exit 77
-    done
+    fi
 fi
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index f294728..4245700 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -195,9 +195,11 @@
       print_error(field, "Unkown type for field: %s\n", field->name().c_str());
       errorCount++;
       continue;
-    } else if (javaType == JAVA_TYPE_OBJECT) {
+    } else if (javaType == JAVA_TYPE_OBJECT &&
+               atomDecl->code < PULL_ATOM_START_ID) {
       // Allow attribution chain, but only at position 1.
-      print_error(field, "Message type not allowed for field: %s\n",
+      print_error(field,
+                  "Message type not allowed for field in pushed atoms: %s\n",
                   field->name().c_str());
       errorCount++;
       continue;
@@ -233,12 +235,19 @@
     java_type_t javaType = java_type(field);
 
     AtomField atField(field->name(), javaType);
+    // Generate signature for pushed atoms
+    if (atomDecl->code < PULL_ATOM_START_ID) {
+      if (javaType == JAVA_TYPE_ENUM) {
+        // All enums are treated as ints when it comes to function signatures.
+        signature->push_back(JAVA_TYPE_INT);
+        collate_enums(*field->enum_type(), &atField);
+      } else {
+        signature->push_back(javaType);
+      }
+    }
     if (javaType == JAVA_TYPE_ENUM) {
       // All enums are treated as ints when it comes to function signatures.
-      signature->push_back(JAVA_TYPE_INT);
       collate_enums(*field->enum_type(), &atField);
-    } else {
-      signature->push_back(javaType);
     }
     atomDecl->fields.push_back(atField);
 
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index ccdd145..31b8b07 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -34,6 +34,8 @@
 using google::protobuf::Descriptor;
 using google::protobuf::FieldDescriptor;
 
+const int PULL_ATOM_START_ID = 10000;
+
 /**
  * The types for atom parameters.
  */
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 83a6631..9915479 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -18,8 +18,6 @@
 namespace android {
 namespace stats_log_api_gen {
 
-const int PULL_ATOM_START_ID = 1000;
-
 int maxPushedAtomId = 2;
 
 using android::os::statsd::Atom;