Merge "Dismiss the PiP if user changes setting while PiP is open." into oc-dev
diff --git a/api/current.txt b/api/current.txt
index 22082db..9b6227f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -696,6 +696,7 @@
     field public static final int hyphenationFrequency = 16843998; // 0x10104de
     field public static final int icon = 16842754; // 0x1010002
     field public static final int iconPreview = 16843337; // 0x1010249
+    field public static final int iconSpaceReserved = 16844132; // 0x1010564
     field public static final int iconTint = 16844129; // 0x1010561
     field public static final int iconTintMode = 16844130; // 0x1010562
     field public static final int iconifiedByDefault = 16843514; // 0x10102fa
@@ -20890,7 +20891,8 @@
     method public int getContentType();
     method public int getFlags();
     method public int getUsage();
-    method public static int getVolumeControlStream(android.media.AudioAttributes);
+    method public static deprecated int getVolumeControlStream(android.media.AudioAttributes);
+    method public int getVolumeControlStream();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
     field public static final int CONTENT_TYPE_MUSIC = 2; // 0x2
@@ -32047,6 +32049,7 @@
     method public int getWidgetLayoutResource();
     method public boolean hasKey();
     method public boolean isEnabled();
+    method public boolean isIconSpaceReserved();
     method public boolean isPersistent();
     method public boolean isRecycleEnabled();
     method public boolean isSelectable();
@@ -32081,6 +32084,7 @@
     method public void setFragment(java.lang.String);
     method public void setIcon(android.graphics.drawable.Drawable);
     method public void setIcon(int);
+    method public void setIconSpaceReserved(boolean);
     method public void setIntent(android.content.Intent);
     method public void setKey(java.lang.String);
     method public void setLayoutResource(int);
@@ -41078,9 +41082,9 @@
   public static final class FontConfig.Font implements android.os.Parcelable {
     method public int describeContents();
     method public android.text.FontConfig.Axis[] getAxes();
-    method public android.os.ParcelFileDescriptor getFd();
     method public java.lang.String getFontName();
     method public int getTtcIndex();
+    method public android.net.Uri getUri();
     method public int getWeight();
     method public boolean isItalic();
     method public void writeToParcel(android.os.Parcel, int);
@@ -48827,6 +48831,7 @@
     method public int getRendererRequestedPriority();
     method public deprecated float getScale();
     method public android.webkit.WebSettings getSettings();
+    method public android.view.textclassifier.TextClassifier getTextClassifier();
     method public java.lang.String getTitle();
     method public java.lang.String getUrl();
     method public android.webkit.WebChromeClient getWebChromeClient();
@@ -48873,6 +48878,7 @@
     method public void setNetworkAvailable(boolean);
     method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
     method public void setRendererPriorityPolicy(int, boolean);
+    method public void setTextClassifier(android.view.textclassifier.TextClassifier);
     method public deprecated void setVerticalScrollbarOverlay(boolean);
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public static void setWebContentsDebuggingEnabled(boolean);
diff --git a/api/system-current.txt b/api/system-current.txt
index 2ad32f2..515cf97 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -810,6 +810,7 @@
     field public static final int hyphenationFrequency = 16843998; // 0x10104de
     field public static final int icon = 16842754; // 0x1010002
     field public static final int iconPreview = 16843337; // 0x1010249
+    field public static final int iconSpaceReserved = 16844132; // 0x1010564
     field public static final int iconTint = 16844129; // 0x1010561
     field public static final int iconTintMode = 16844130; // 0x1010562
     field public static final int iconifiedByDefault = 16843514; // 0x10102fa
@@ -22626,7 +22627,8 @@
     method public int getContentType();
     method public int getFlags();
     method public int getUsage();
-    method public static int getVolumeControlStream(android.media.AudioAttributes);
+    method public static deprecated int getVolumeControlStream(android.media.AudioAttributes);
+    method public int getVolumeControlStream();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
     field public static final int CONTENT_TYPE_MUSIC = 2; // 0x2
@@ -34892,6 +34894,7 @@
     method public int getWidgetLayoutResource();
     method public boolean hasKey();
     method public boolean isEnabled();
+    method public boolean isIconSpaceReserved();
     method public boolean isPersistent();
     method public boolean isRecycleEnabled();
     method public boolean isSelectable();
@@ -34926,6 +34929,7 @@
     method public void setFragment(java.lang.String);
     method public void setIcon(android.graphics.drawable.Drawable);
     method public void setIcon(int);
+    method public void setIconSpaceReserved(boolean);
     method public void setIntent(android.content.Intent);
     method public void setKey(java.lang.String);
     method public void setLayoutResource(int);
@@ -44532,9 +44536,9 @@
   public static final class FontConfig.Font implements android.os.Parcelable {
     method public int describeContents();
     method public android.text.FontConfig.Axis[] getAxes();
-    method public android.os.ParcelFileDescriptor getFd();
     method public java.lang.String getFontName();
     method public int getTtcIndex();
+    method public android.net.Uri getUri();
     method public int getWeight();
     method public boolean isItalic();
     method public void writeToParcel(android.os.Parcel, int);
@@ -52378,6 +52382,7 @@
     method public int getRendererRequestedPriority();
     method public deprecated float getScale();
     method public android.webkit.WebSettings getSettings();
+    method public android.view.textclassifier.TextClassifier getTextClassifier();
     method public java.lang.String getTitle();
     method public java.lang.String getUrl();
     method public android.webkit.WebChromeClient getWebChromeClient();
@@ -52425,6 +52430,7 @@
     method public void setNetworkAvailable(boolean);
     method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
     method public void setRendererPriorityPolicy(int, boolean);
+    method public void setTextClassifier(android.view.textclassifier.TextClassifier);
     method public deprecated void setVerticalScrollbarOverlay(boolean);
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public static void setWebContentsDebuggingEnabled(boolean);
@@ -52666,6 +52672,7 @@
     method public abstract float getScale();
     method public abstract android.webkit.WebViewProvider.ScrollDelegate getScrollDelegate();
     method public abstract android.webkit.WebSettings getSettings();
+    method public default android.view.textclassifier.TextClassifier getTextClassifier();
     method public abstract java.lang.String getTitle();
     method public abstract java.lang.String getTouchIconUrl();
     method public abstract java.lang.String getUrl();
@@ -52718,6 +52725,7 @@
     method public abstract void setNetworkAvailable(boolean);
     method public abstract void setPictureListener(android.webkit.WebView.PictureListener);
     method public abstract void setRendererPriorityPolicy(int, boolean);
+    method public default void setTextClassifier(android.view.textclassifier.TextClassifier);
     method public abstract void setVerticalScrollbarOverlay(boolean);
     method public abstract void setWebChromeClient(android.webkit.WebChromeClient);
     method public abstract void setWebViewClient(android.webkit.WebViewClient);
diff --git a/api/test-current.txt b/api/test-current.txt
index 7d96895..051e2e6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -696,6 +696,7 @@
     field public static final int hyphenationFrequency = 16843998; // 0x10104de
     field public static final int icon = 16842754; // 0x1010002
     field public static final int iconPreview = 16843337; // 0x1010249
+    field public static final int iconSpaceReserved = 16844132; // 0x1010564
     field public static final int iconTint = 16844129; // 0x1010561
     field public static final int iconTintMode = 16844130; // 0x1010562
     field public static final int iconifiedByDefault = 16843514; // 0x10102fa
@@ -21003,7 +21004,8 @@
     method public int getContentType();
     method public int getFlags();
     method public int getUsage();
-    method public static int getVolumeControlStream(android.media.AudioAttributes);
+    method public static deprecated int getVolumeControlStream(android.media.AudioAttributes);
+    method public int getVolumeControlStream();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
     field public static final int CONTENT_TYPE_MUSIC = 2; // 0x2
@@ -32184,6 +32186,7 @@
     method public int getWidgetLayoutResource();
     method public boolean hasKey();
     method public boolean isEnabled();
+    method public boolean isIconSpaceReserved();
     method public boolean isPersistent();
     method public boolean isRecycleEnabled();
     method public boolean isSelectable();
@@ -32218,6 +32221,7 @@
     method public void setFragment(java.lang.String);
     method public void setIcon(android.graphics.drawable.Drawable);
     method public void setIcon(int);
+    method public void setIconSpaceReserved(boolean);
     method public void setIntent(android.content.Intent);
     method public void setKey(java.lang.String);
     method public void setLayoutResource(int);
@@ -41285,9 +41289,9 @@
   public static final class FontConfig.Font implements android.os.Parcelable {
     method public int describeContents();
     method public android.text.FontConfig.Axis[] getAxes();
-    method public android.os.ParcelFileDescriptor getFd();
     method public java.lang.String getFontName();
     method public int getTtcIndex();
+    method public android.net.Uri getUri();
     method public int getWeight();
     method public boolean isItalic();
     method public void writeToParcel(android.os.Parcel, int);
@@ -49210,6 +49214,7 @@
     method public int getRendererRequestedPriority();
     method public deprecated float getScale();
     method public android.webkit.WebSettings getSettings();
+    method public android.view.textclassifier.TextClassifier getTextClassifier();
     method public java.lang.String getTitle();
     method public java.lang.String getUrl();
     method public android.webkit.WebChromeClient getWebChromeClient();
@@ -49256,6 +49261,7 @@
     method public void setNetworkAvailable(boolean);
     method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
     method public void setRendererPriorityPolicy(int, boolean);
+    method public void setTextClassifier(android.view.textclassifier.TextClassifier);
     method public deprecated void setVerticalScrollbarOverlay(boolean);
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public static void setWebContentsDebuggingEnabled(boolean);
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 4d14277..d3adce7 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -83,6 +83,7 @@
  * @attr ref android.R.styleable#Preference_shouldDisableView
  * @attr ref android.R.styleable#Preference_recycleEnabled
  * @attr ref android.R.styleable#Preference_singleLineTitle
+ * @attr ref android.R.styleable#Preference_iconSpaceReserved
  */
 public class Preference implements Comparable<Preference> {
     /**
@@ -135,6 +136,7 @@
     private boolean mParentDependencyMet = true;
     private boolean mRecycleEnabled = true;
     private boolean mSingleLineTitle = true;
+    private boolean mIconSpaceReserved;
 
     /**
      * @see #setShouldDisableView(boolean)
@@ -302,7 +304,11 @@
                 case com.android.internal.R.styleable.Preference_singleLineTitle:
                     mSingleLineTitle = a.getBoolean(attr, mSingleLineTitle);
                     break;
-            }
+
+                case com.android.internal.R.styleable.Preference_iconSpaceReserved:
+                    mIconSpaceReserved = a.getBoolean(attr, mIconSpaceReserved);
+                    break;
+           }
         }
         a.recycle();
     }
@@ -631,7 +637,11 @@
                     imageView.setImageDrawable(mIcon);
                 }
             }
-            imageView.setVisibility(mIcon != null ? View.VISIBLE : View.GONE);
+            if (mIcon != null) {
+                imageView.setVisibility(View.VISIBLE);
+            } else {
+                imageView.setVisibility(mIconSpaceReserved ? View.INVISIBLE : View.GONE);
+            }
         }
 
         final View imageFrame = view.findViewById(com.android.internal.R.id.icon_frame);
@@ -931,6 +941,25 @@
     }
 
     /**
+     * Sets whether to reserve the space of this Preference icon view when no icon is provided.
+     *
+     * @param iconSpaceReserved set {@code true} if the space for the icon view should be reserved
+     */
+    public void setIconSpaceReserved(boolean iconSpaceReserved) {
+        mIconSpaceReserved = iconSpaceReserved;
+        notifyChanged();
+    }
+
+    /**
+     * Gets whether the space this preference icon view is reserved.
+     *
+     * @see #setIconSpaceReserved(boolean)
+     * @return {@code true} if the space of this preference icon view is reserved
+     */
+    public boolean isIconSpaceReserved() {
+        return mIconSpaceReserved;
+    }
+    /**
      * Returns a unique ID for this Preference.  This ID should be unique across all
      * Preference objects in a hierarchy.
      *
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 70f9bdd..14d3ad7 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -22,13 +22,11 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.FontListParser;
+import android.net.Uri;
 import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 
-import java.io.IOException;
 import java.lang.annotation.Retention;
-import java.util.Arrays;
 
 
 /**
@@ -44,20 +42,6 @@
     }
 
     /**
-     * For duplicating file descriptors.
-     *
-     * Note that this copy constructor can not be usable for deep copy.
-     * @hide
-     */
-    public FontConfig(@NonNull FontConfig config) {
-        mFamilies = new Family[config.mFamilies.length];
-        for (int i = 0; i < config.mFamilies.length; ++i) {
-            mFamilies[i] = new Family(config.mFamilies[i]);
-        }
-        mAliases = Arrays.copyOf(config.mAliases, config.mAliases.length);
-    }
-
-    /**
      * Returns the ordered list of families included in the system fonts.
      */
     public @NonNull Family[] getFamilies() {
@@ -174,7 +158,7 @@
         private final @NonNull Axis[] mAxes;
         private final int mWeight;
         private final boolean mIsItalic;
-        private @Nullable ParcelFileDescriptor mFd;
+        private Uri mUri;
 
         /**
          * @hide
@@ -186,29 +170,6 @@
             mAxes = axes;
             mWeight = weight;
             mIsItalic = isItalic;
-            mFd = null;
-        }
-
-        /**
-         * This is for duplicating FileDescriptors.
-         *
-         * Note that this copy ctor doesn't deep copy the members.
-         *
-         * @hide
-         */
-        public Font(Font origin) {
-            mFontName = origin.mFontName;
-            mTtcIndex = origin.mTtcIndex;
-            mAxes = origin.mAxes;
-            mWeight = origin.mWeight;
-            mIsItalic = origin.mIsItalic;
-            if (origin.mFd != null) {
-                try {
-                    mFd = origin.mFd.dup();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
         }
 
         /**
@@ -247,17 +208,20 @@
         }
 
         /**
-         * Returns a file descriptor to access the specified font. This should be closed after use.
+         * Returns the content uri associated to this font.
+         *
+         * You can reach to the font contents by calling {@link
+         * android.content.ContentResolver#openInputStream}.
          */
-        public @Nullable ParcelFileDescriptor getFd() {
-            return mFd;
+        public @Nullable Uri getUri() {
+            return mUri;
         }
 
         /**
          * @hide
          */
-        public void setFd(@NonNull ParcelFileDescriptor fd) {
-            mFd = fd;
+        public void setUri(@NonNull Uri uri) {
+            mUri = uri;
         }
 
         /**
@@ -269,11 +233,7 @@
             mAxes = in.createTypedArray(Axis.CREATOR);
             mWeight = in.readInt();
             mIsItalic = in.readInt() == 1;
-            if (in.readInt() == 1) { /* has FD */
-                mFd = ParcelFileDescriptor.CREATOR.createFromParcel(in);
-            } else {
-                mFd = null;
-            }
+            mUri = in.readTypedObject(Uri.CREATOR);
         }
 
         @Override
@@ -283,10 +243,7 @@
             out.writeTypedArray(mAxes, flag);
             out.writeInt(mWeight);
             out.writeInt(mIsItalic ? 1 : 0);
-            out.writeInt(mFd == null ? 0 : 1);
-            if (mFd != null) {
-                mFd.writeToParcel(out, flag);
-            }
+            out.writeTypedObject(mUri, flag);
         }
 
         @Override
@@ -425,22 +382,6 @@
         }
 
         /**
-         * For duplicating file descriptor underlying Font object.
-         *
-         * This copy constructor is not for deep copying.
-         * @hide
-         */
-        public Family(Family origin) {
-            mName = origin.mName;
-            mLanguage = origin.mLanguage;
-            mVariant = origin.mVariant;
-            mFonts = new Font[origin.mFonts.length];
-            for (int i = 0; i < origin.mFonts.length; ++i) {
-                mFonts[i] = new Font(origin.mFonts[i]);
-            }
-        }
-
-        /**
          * Returns the name given by the system to this font family.
          */
         public @Nullable String getName() {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index e590739..076b33c 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -137,7 +137,10 @@
                 } break;
                 case DRAW_FINISHED_MSG: {
                     mDrawFinished = true;
-                    invalidate();
+                    if (mAttachedToWindow) {
+                        notifyDrawFinished();
+                        invalidate();
+                    }
                 } break;
             }
         }
@@ -188,9 +191,12 @@
     private Translator mTranslator;
 
     private boolean mGlobalListenersAdded;
+    private boolean mAttachedToWindow;
 
     private int mSurfaceFlags = SurfaceControl.HIDDEN;
 
+    private int mPendingReportDraws;
+
     public SurfaceView(Context context) {
         this(context, null);
     }
@@ -227,6 +233,7 @@
         mViewVisibility = getVisibility() == VISIBLE;
         mRequestedVisible = mViewVisibility && mWindowVisibility;
 
+        mAttachedToWindow = true;
         if (!mGlobalListenersAdded) {
             ViewTreeObserver observer = getViewTreeObserver();
             observer.addOnScrollChangedListener(mScrollChangedListener);
@@ -261,8 +268,17 @@
         updateSurface();
     }
 
+    void notifyDrawFinished() {
+        ViewRootImpl viewRoot = getViewRootImpl();
+        if (viewRoot != null) {
+            viewRoot.pendingDrawFinished();
+        }
+        mPendingReportDraws--;
+    }
+
     @Override
     protected void onDetachedFromWindow() {
+        mAttachedToWindow = false;
         if (mGlobalListenersAdded) {
             ViewTreeObserver observer = getViewTreeObserver();
             observer.removeOnScrollChangedListener(mScrollChangedListener);
@@ -270,6 +286,10 @@
             mGlobalListenersAdded = false;
         }
 
+        while (mPendingReportDraws > 0) {
+            notifyDrawFinished();
+        }
+
         mRequestedVisible = false;
 
         updateSurface();
@@ -618,6 +638,9 @@
                             if (callbacks == null) {
                                 callbacks = getSurfaceCallbacks();
                             }
+
+                            mPendingReportDraws++;
+                            viewRoot.drawPending();
                             SurfaceCallbackHelper sch =
                                     new SurfaceCallbackHelper(this::onDrawFinished);
                             sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3f52a9d..e924f77 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -61,6 +61,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.hardware.display.DisplayManagerGlobal;
+import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -4170,14 +4171,14 @@
     /**
      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
      * request read access to the content URI(s) contained in the {@link ClipData} object.
-     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
+     * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
      */
     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
 
     /**
      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
      * request write access to the content URI(s) contained in the {@link ClipData} object.
-     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+     * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
      */
     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
 
@@ -4185,8 +4186,8 @@
      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
      * reboots until explicitly revoked with
-     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
-     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+     * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
+     * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
      */
     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
@@ -4195,7 +4196,7 @@
      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
      * match against the original granted URI.
-     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
+     * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
      */
     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
@@ -7895,7 +7896,7 @@
      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
      *                  {@code null} if the service provided no arguments.
      *
-     * @see AccessibilityNodeInfo#setExtraAvailableData
+     * @see AccessibilityNodeInfo#setAvailableExtraData(List)
      */
     public void addExtraDataToAccessibilityNodeInfo(
             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
@@ -9839,7 +9840,7 @@
      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
      * window or serves as a target of cluster navigation.
      *
-     * @see #restoreDefaultFocus(int)
+     * @see #restoreDefaultFocus()
      *
      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
      * @attr ref android.R.styleable#View_focusedByDefault
@@ -9859,7 +9860,7 @@
      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
      *                           {@code false} otherwise.
      *
-     * @see #restoreDefaultFocus(int)
+     * @see #restoreDefaultFocus()
      *
      * @attr ref android.R.styleable#View_focusedByDefault
      */
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index cf52c60..6ec4a2b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2704,8 +2704,40 @@
         }
     }
 
-    private void onDrawFinished() {
+    /**
+     * A count of the number of calls to pendingDrawFinished we
+     * require to notify the WM drawing is complete.
+     *
+     * This starts at 1, for the ViewRootImpl surface itself.
+     * Subsurfaces may debt the value with drawPending.
+     */
+    int mDrawsNeededToReport = 1;
+
+    /**
+     * Delay notifying WM of draw finished until
+     * a balanced call to pendingDrawFinished.
+     */
+    void drawPending() {
+        mDrawsNeededToReport++;
+    }
+
+    void pendingDrawFinished() {
+        if (mDrawsNeededToReport == 0) {
+            throw new RuntimeException("Unbalanced drawPending/pendingDrawFinished calls");
+        }
+        mDrawsNeededToReport--;
+        if (mDrawsNeededToReport == 0) {
+            reportDrawFinished();
+        }
+    }
+
+    private void postDrawFinished() {
+        mHandler.sendEmptyMessage(MSG_DRAW_FINISHED);
+    }
+
+    private void reportDrawFinished() {
         try {
+            mDrawsNeededToReport = 1;
             mWindowSession.finishDrawing(mWindow);
         } catch (RemoteException e) {
             // Have fun!
@@ -2762,15 +2794,12 @@
             }
 
             if (mSurfaceHolder != null && mSurface.isValid()) {
-                SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::onDrawFinished);
+                SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::postDrawFinished);
                 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
 
                 sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
             } else {
-                try {
-                    mWindowSession.finishDrawing(mWindow);
-                } catch (RemoteException e) {
-                }
+                pendingDrawFinished();
             }
         }
     }
@@ -3576,6 +3605,7 @@
     private final static int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26;
     private final static int MSG_UPDATE_POINTER_ICON = 27;
     private final static int MSG_POINTER_CAPTURE_CHANGED = 28;
+    private final static int MSG_DRAW_FINISHED = 29;
 
     final class ViewRootHandler extends Handler {
         @Override
@@ -3627,6 +3657,8 @@
                     return "MSG_UPDATE_POINTER_ICON";
                 case MSG_POINTER_CAPTURE_CHANGED:
                     return "MSG_POINTER_CAPTURE_CHANGED";
+                case MSG_DRAW_FINISHED:
+                    return "MSG_DRAW_FINISHED";
             }
             return super.getMessageName(message);
         }
@@ -3902,6 +3934,9 @@
                 final boolean hasCapture = msg.arg1 != 0;
                 handlePointerCaptureChanged(hasCapture);
             } break;
+            case MSG_DRAW_FINISHED: {
+                pendingDrawFinished();
+            } break;
             }
         }
     }
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index 35c9a29..5487965 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -44,8 +44,6 @@
     private final Object mLangIdLock = new Object();
 
     private final Context mContext;
-    // TODO: Implement a way to close the file descriptors.
-    private ParcelFileDescriptor mSmartSelectionFd;
     private ParcelFileDescriptor mLangIdFd;
     private TextClassifier mDefault;
     private LangId mLangId;
@@ -61,15 +59,7 @@
     public TextClassifier getDefaultTextClassifier() {
         synchronized (mTextClassifierLock) {
             if (mDefault == null) {
-                try {
-                    mSmartSelectionFd = ParcelFileDescriptor.open(
-                            new File("/etc/textclassifier/textclassifier.smartselection.en.model"),
-                            ParcelFileDescriptor.MODE_READ_ONLY);
-                    mDefault = new TextClassifierImpl(mContext, mSmartSelectionFd);
-                } catch (FileNotFoundException e) {
-                    Log.e(LOG_TAG, "Error accessing 'text classifier selection' model file.", e);
-                    mDefault = TextClassifier.NO_OP;
-                }
+                mDefault = new TextClassifierImpl(mContext);
             }
             return mDefault;
         }
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 66a62c3..f634a1b 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -38,17 +38,24 @@
 import android.util.Patterns;
 import android.view.View;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Default implementation of the {@link TextClassifier} interface.
@@ -62,16 +69,21 @@
 final class TextClassifierImpl implements TextClassifier {
 
     private static final String LOG_TAG = "TextClassifierImpl";
-
-    private final Object mSmartSelectionLock = new Object();
+    private static final String MODEL_DIR = "/etc/textclassifier/";
+    private static final String MODEL_FILE_REGEX = "textclassifier\\.smartselection\\.(.*)\\.model";
 
     private final Context mContext;
-    private final ParcelFileDescriptor mFd;
+
+    private final Object mSmartSelectionLock = new Object();
+    @GuardedBy("mSmartSelectionLock") // Do not access outside this lock.
+    private Map<Locale, String> mModelFilePaths;
+    @GuardedBy("mSmartSelectionLock") // Do not access outside this lock.
+    private Locale mLocale;
+    @GuardedBy("mSmartSelectionLock") // Do not access outside this lock.
     private SmartSelection mSmartSelection;
 
-    TextClassifierImpl(Context context, ParcelFileDescriptor fd) {
+    TextClassifierImpl(Context context) {
         mContext = Preconditions.checkNotNull(context);
-        mFd = Preconditions.checkNotNull(fd);
     }
 
     @Override
@@ -81,15 +93,16 @@
         validateInput(text, selectionStartIndex, selectionEndIndex);
         try {
             if (text.length() > 0) {
+                final SmartSelection smartSelection = getSmartSelection(defaultLocales);
                 final String string = text.toString();
-                final int[] startEnd = getSmartSelection()
-                        .suggest(string, selectionStartIndex, selectionEndIndex);
+                final int[] startEnd = smartSelection.suggest(
+                        string, selectionStartIndex, selectionEndIndex);
                 final int start = startEnd[0];
                 final int end = startEnd[1];
                 if (start >= 0 && end <= string.length() && start <= end) {
                     final TextSelection.Builder tsBuilder = new TextSelection.Builder(start, end);
                     final SmartSelection.ClassificationResult[] results =
-                            getSmartSelection().classifyText(
+                            smartSelection.classifyText(
                                     string, start, end,
                                     getHintFlags(string, start, end));
                     final int size = results.length;
@@ -120,7 +133,7 @@
         try {
             if (text.length() > 0) {
                 final String string = text.toString();
-                SmartSelection.ClassificationResult[] results = getSmartSelection()
+                SmartSelection.ClassificationResult[] results = getSmartSelection(defaultLocales)
                         .classifyText(string, startIndex, endIndex,
                                 getHintFlags(string, startIndex, endIndex));
                 if (results.length > 0) {
@@ -147,7 +160,7 @@
         Preconditions.checkArgument(text != null);
         try {
             return LinksInfoFactory.create(
-                    mContext, getSmartSelection(), text.toString(), linkMask);
+                    mContext, getSmartSelection(defaultLocales), text.toString(), linkMask);
         } catch (Throwable t) {
             // Avoid throwing from this method. Log the error.
             Log.e(LOG_TAG, "Error getting links info.", t);
@@ -156,15 +169,69 @@
         return TextClassifier.NO_OP.getLinks(text, linkMask, defaultLocales);
     }
 
-    private SmartSelection getSmartSelection() throws FileNotFoundException {
+    private SmartSelection getSmartSelection(LocaleList localeList) throws FileNotFoundException {
         synchronized (mSmartSelectionLock) {
-            if (mSmartSelection == null) {
-                mSmartSelection = new SmartSelection(mFd.getFd());
+            localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList;
+            final Locale locale = findBestSupportedLocaleLocked(localeList);
+            if (mSmartSelection == null || !Objects.equals(mLocale, locale)) {
+                destroySmartSelectionIfExistsLocked();
+                mSmartSelection = new SmartSelection(
+                        ParcelFileDescriptor.open(
+                                // findBestSupportedLocaleLocked should have initialized
+                                // mModelFilePaths
+                                new File(mModelFilePaths.get(locale)),
+                                ParcelFileDescriptor.MODE_READ_ONLY)
+                                .getFd());
+                mLocale = locale;
             }
             return mSmartSelection;
         }
     }
 
+    @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
+    private void destroySmartSelectionIfExistsLocked() {
+        if (mSmartSelection != null) {
+            mSmartSelection.close();
+            mSmartSelection = null;
+        }
+    }
+
+    @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
+    @Nullable
+    private Locale findBestSupportedLocaleLocked(LocaleList localeList) {
+        final List<Locale.LanguageRange> languageRangeList = Locale.LanguageRange.parse(
+                new StringJoiner(",")
+                        // Specified localeList takes priority over the system default
+                        .add(localeList.toLanguageTags())
+                        .add(LocaleList.getDefault().toLanguageTags())
+                        .toString());
+        return Locale.lookup(languageRangeList, loadModelFilePathsLocked().keySet());
+    }
+
+    @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
+    private Map<Locale, String> loadModelFilePathsLocked() {
+        if (mModelFilePaths == null) {
+            final Map<Locale, String> modelFilePaths = new HashMap<>();
+            final File modelsDir = new File(MODEL_DIR);
+            if (modelsDir.exists() && modelsDir.isDirectory()) {
+                final File[] models = modelsDir.listFiles();
+                final Pattern modelFilenamePattern = Pattern.compile(MODEL_FILE_REGEX);
+                final int size = models.length;
+                for (int i = 0; i < size; i++) {
+                    final File modelFile = models[i];
+                    final Matcher matcher = modelFilenamePattern.matcher(modelFile.getName());
+                    if (matcher.matches() && modelFile.isFile()) {
+                        final String language = matcher.group(1);
+                        final Locale locale = Locale.forLanguageTag(language);
+                        modelFilePaths.put(locale, modelFile.getAbsolutePath());
+                    }
+                }
+            }
+            mModelFilePaths = modelFilePaths;
+        }
+        return mModelFilePaths;
+    }
+
     private TextClassificationResult createClassificationResult(
             SmartSelection.ClassificationResult[] classifications, CharSequence text) {
         final TextClassificationResult.Builder builder = new TextClassificationResult.Builder()
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index c2b4138..bc49123 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.Widget;
 import android.content.Context;
@@ -58,6 +59,7 @@
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
+import android.view.textclassifier.TextClassifier;
 import android.widget.AbsoluteLayout;
 
 import java.io.BufferedWriter;
@@ -2249,6 +2251,23 @@
     public boolean getRendererPriorityWaivedWhenNotVisible() {
         return mProvider.getRendererPriorityWaivedWhenNotVisible();
     }
+
+    /**
+     * Sets the {@link TextClassifier} for this WebView.
+     */
+    public void setTextClassifier(@Nullable TextClassifier textClassifier) {
+        mProvider.setTextClassifier(textClassifier);
+    }
+
+    /**
+     * Returns the {@link TextClassifier} used by this WebView.
+     * If no TextClassifier has been set, this WebView uses the default set by the system.
+     */
+    @NonNull
+    public TextClassifier getTextClassifier() {
+        return mProvider.getTextClassifier();
+    }
+
     //-------------------------------------------------------------------------
     // Interface for WebView providers
     //-------------------------------------------------------------------------
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 5724a9b..aa1ffa2 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -16,6 +16,8 @@
 
 package android.webkit;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.content.res.Configuration;
 import android.content.Intent;
@@ -41,6 +43,7 @@
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
+import android.view.textclassifier.TextClassifier;
 import android.webkit.WebView.HitTestResult;
 import android.webkit.WebView.PictureListener;
 import android.webkit.WebView.VisualStateCallback;
@@ -275,6 +278,12 @@
 
     public boolean getRendererPriorityWaivedWhenNotVisible();
 
+    @SuppressWarnings("unused")
+    public default void setTextClassifier(@Nullable TextClassifier textClassifier) {}
+
+    @NonNull
+    public default TextClassifier getTextClassifier() { return TextClassifier.NO_OP; }
+
     //-------------------------------------------------------------------------
     // Provider internal methods
     //-------------------------------------------------------------------------
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 1937187..99b91bd 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -6873,9 +6873,11 @@
                     mTransientStateViews.put(position, scrap);
                 } else {
                     // Otherwise, we'll have to remove the view and start over.
+                    clearScrapForRebind(scrap);
                     getSkippedScrap().add(scrap);
                 }
             } else {
+                clearScrapForRebind(scrap);
                 if (mViewTypeCount == 1) {
                     mCurrentScrap.add(scrap);
                 } else {
@@ -7098,12 +7100,12 @@
                         }
                     } else if (params.scrappedFromPosition == position) {
                         final View scrap = scrapViews.remove(i);
-                        clearAccessibilityFromScrap(scrap);
+                        clearScrapForRebind(scrap);
                         return scrap;
                     }
                 }
                 final View scrap = scrapViews.remove(size - 1);
-                clearAccessibilityFromScrap(scrap);
+                clearScrapForRebind(scrap);
                 return scrap;
             } else {
                 return null;
@@ -7117,7 +7119,7 @@
             }
         }
 
-        private void clearAccessibilityFromScrap(View view) {
+        private void clearScrapForRebind(View view) {
             view.clearAccessibilityFocus();
             view.setAccessibilityDelegate(null);
         }
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 1c0c4ef..12e35a1 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1639,7 +1639,7 @@
                     final View focusChild = getAccessibilityFocusedChild(focusHost);
                     if (focusChild != null) {
                         if (!dataChanged || isDirectChildHeaderOrFooter(focusChild)
-                                || focusChild.hasTransientState() || mAdapterHasStableIds) {
+                                || (focusChild.hasTransientState() && mAdapterHasStableIds)) {
                             // The views won't be changing, so try to maintain
                             // focus on the current host and virtual view.
                             accessibilityFocusLayoutRestoreView = focusHost;
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 995f2c3..a3b2705 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7226,6 +7226,10 @@
         <!-- Whether to use single line for the preference title text. By default, preference title
              will be constrained to one line, so the default value of this attribute is true. -->
         <attr name="singleLineTitle" format="boolean" />
+        <!-- Whether the space for the preference icon view will be reserved. By default, preference
+             icon view visibility will be set to GONE when there is no icon provided, so the default
+             value of this attribute is false. -->
+        <attr name="iconSpaceReserved" format="boolean" />
     </declare-styleable>
 
     <!-- Base attributes available to CheckBoxPreference. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 876d44d..6e20208 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2813,6 +2813,7 @@
         <public name="iconTint" />
         <public name="iconTintMode" />
         <public name="maxAspectRatio"/>
+        <public name="iconSpaceReserved"/>
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index b78df34..ff9f11d 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -189,9 +189,8 @@
                 skip(parser);
             }
         }
-        String fullFilename = "/system/fonts/" +
-                FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
-        return new FontConfig.Font(fullFilename, index,
+        String sanitizedName = FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
+        return new FontConfig.Font(sanitizedName, index,
                 axes.toArray(new FontConfig.Axis[axes.size()]), weight, isItalic);
     }
 
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 228d950..8c3a2e8 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1003,21 +1003,22 @@
             Map<String, ByteBuffer> bufferForPath) {
         FontFamily fontFamily = new FontFamily(family.getLanguage(), family.getVariant());
         for (FontConfig.Font font : family.getFonts()) {
-            ByteBuffer fontBuffer = bufferForPath.get(font.getFontName());
+            String fullPathName = "/system/fonts/" + font.getFontName();
+            ByteBuffer fontBuffer = bufferForPath.get(fullPathName);
             if (fontBuffer == null) {
-                try (FileInputStream file = new FileInputStream(font.getFontName())) {
+                try (FileInputStream file = new FileInputStream(fullPathName)) {
                     FileChannel fileChannel = file.getChannel();
                     long fontSize = fileChannel.size();
                     fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
-                    bufferForPath.put(font.getFontName(), fontBuffer);
+                    bufferForPath.put(fullPathName, fontBuffer);
                 } catch (IOException e) {
-                    Log.e(TAG, "Error mapping font file " + font.getFontName());
+                    Log.e(TAG, "Error mapping font file " + fullPathName);
                     continue;
                 }
             }
             if (!fontFamily.addFontFromBuffer(fontBuffer, font.getTtcIndex(), font.getAxes(),
                     font.getWeight(), font.isItalic() ? Builder.ITALIC : Builder.NORMAL)) {
-                Log.e(TAG, "Error creating font " + font.getFontName() + "#" + font.getTtcIndex());
+                Log.e(TAG, "Error creating font " + fullPathName + "#" + font.getTtcIndex());
             }
         }
         fontFamily.freeze();
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index ce58a9c..77a82ec 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -912,6 +912,8 @@
                 return USAGE_UNKNOWN;
         }
     }
+
+    // TODO remove, replaced by non-static API getVolumeControlStream()
     /**
      * Returns the stream type matching the given attributes for volume control.
      * Use this method to derive the stream type needed to configure the volume
@@ -925,6 +927,7 @@
      *     the attributes, or {@link AudioManager#USE_DEFAULT_STREAM_TYPE} if there isn't a direct
      *     match. Note that <code>USE_DEFAULT_STREAM_TYPE</code> is not a valid value
      *     for {@link AudioManager#setStreamVolume(int, int, int)}.
+     * @deprecated use {@link #getVolumeControlStream()}
      */
     public static int getVolumeControlStream(@NonNull AudioAttributes aa) {
         if (aa == null) {
@@ -934,6 +937,24 @@
     }
 
     /**
+     * Returns the stream type matching this {@code AudioAttributes} instance for volume control.
+     * Use this method to derive the stream type needed to configure the volume
+     * control slider in an {@link android.app.Activity} with
+     * {@link android.app.Activity#setVolumeControlStream(int)} for playback conducted with these
+     * attributes.
+     * <BR>Do not use this method to set the stream type on an audio player object
+     * (e.g. {@link AudioTrack}, {@link MediaPlayer}) as this is deprecated,
+     * use {@code AudioAttributes} instead.
+     * @return a valid stream type for {@code Activity} or stream volume control that matches
+     *     the attributes, or {@link AudioManager#USE_DEFAULT_STREAM_TYPE} if there isn't a direct
+     *     match. Note that {@code USE_DEFAULT_STREAM_TYPE} is not a valid value
+     *     for {@link AudioManager#setStreamVolume(int, int, int)}.
+     */
+    public int getVolumeControlStream() {
+        return toVolumeStreamType(true /*fromGetVolumeControlStream*/, this);
+    }
+
+    /**
      * @hide
      * Only use to get which stream type should be used for volume control, NOT for audio playback
      * (all audio playback APIs are supposed to take AudioAttributes as input parameters)
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index 187e35a..f11a9cd 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -113,12 +113,14 @@
                             }
                             // Notify we are done.
                             mState = STATE_UPDATED;
+                            mDocumentInfo.updated = true;
                             notifyUpdateCompleted();
                         }
                     }
                 } else {
                     // We always notify after a write.
                     mState = STATE_UPDATED;
+                    mDocumentInfo.updated = true;
                     notifyUpdateCompleted();
                 }
                 runPendingCommand();
@@ -229,6 +231,7 @@
                   mDocumentInfo, oldAttributes, attributes, preview, mCommandResultCallback);
             scheduleCommand(command);
 
+            mDocumentInfo.updated = false;
             mState = STATE_UPDATING;
         // If no layout in progress and we don't have all pages - schedule a write.
         } else if ((!(mCurrentCommand instanceof LayoutCommand)
@@ -249,6 +252,7 @@
                     mDocumentInfo.fileProvider, mCommandResultCallback);
             scheduleCommand(command);
 
+            mDocumentInfo.updated = false;
             mState = STATE_UPDATING;
         } else {
             willUpdate = false;
@@ -396,7 +400,7 @@
 
     private void notifyUpdateFailed(CharSequence error) {
         if (DEBUG) {
-            Log.i(LOG_TAG, "[CALLING] onUpdateCompleted()");
+            Log.i(LOG_TAG, "[CALLING] notifyUpdateFailed()");
         }
         mUpdateCallbacks.onUpdateFailed(error);
     }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index f6df995..4cce166 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -491,8 +491,6 @@
 
         setState(STATE_UPDATE_FAILED);
 
-        updateOptionsUi();
-
         mPrintedDocument.kill(message);
     }
 
@@ -502,7 +500,6 @@
                 && canUpdateDocument() && updateDocument(true)) {
             ensurePreviewUiShown();
             setState(STATE_CONFIGURING);
-            updateOptionsUi();
         }
     }
 
@@ -579,7 +576,6 @@
                 updatePrintPreviewController(document.changed);
 
                 setState(STATE_CONFIGURING);
-                updateOptionsUi();
             } break;
         }
     }
@@ -600,8 +596,6 @@
         }
 
         setState(STATE_UPDATE_FAILED);
-
-        updateOptionsUi();
     }
 
     @Override
@@ -734,7 +728,6 @@
             updateOptionsUi();
         } else {
             setState(STATE_CREATE_FILE_FAILED);
-            updateOptionsUi();
             // Calling finish here does not invoke lifecycle callbacks but we
             // update the print job in onPause if finishing, hence post a message.
             mDestinationSpinner.post(new Runnable() {
@@ -958,12 +951,14 @@
                     Log.i(LOG_TAG, "[state]" + state);
                 }
                 mState = state;
+                updateOptionsUi();
             }
         } else {
             if (DEBUG) {
                 Log.i(LOG_TAG, "[state]" + state);
             }
             mState = state;
+            updateOptionsUi();
         }
     }
 
@@ -1230,6 +1225,7 @@
 
         final boolean willUpdate = mPrintedDocument.update(mPrintJob.getAttributes(),
                 pages, preview);
+        updateOptionsUi();
 
         if (willUpdate && !mPrintedDocument.hasLaidOutPages()) {
             // When the update is done we update the print preview.
@@ -1254,7 +1250,6 @@
 
     private void cancelPrint() {
         setState(STATE_PRINT_CANCELED);
-        updateOptionsUi();
         mPrintedDocument.cancel(true);
         doFinish();
     }
@@ -1274,7 +1269,6 @@
     private void confirmPrint() {
         setState(STATE_PRINT_CONFIRMED);
 
-        updateOptionsUi();
         addCurrentPrinterToHistory();
         setUserPrinted();
 
@@ -1629,6 +1623,8 @@
         // Always update the summary.
         updateSummary();
 
+        mDestinationSpinner.setEnabled(!isFinalState(mState));
+
         if (mState == STATE_PRINT_CONFIRMED
                 || mState == STATE_PRINT_COMPLETED
                 || mState == STATE_PRINT_CANCELED
@@ -1636,9 +1632,6 @@
                 || mState == STATE_CREATE_FILE_FAILED
                 || mState == STATE_PRINTER_UNAVAILABLE
                 || mState == STATE_UPDATE_SLOW) {
-            if (mState != STATE_PRINTER_UNAVAILABLE) {
-                mDestinationSpinner.setEnabled(false);
-            }
             disableOptionsUi(isFinalState(mState));
             return;
         }
@@ -1927,7 +1920,7 @@
             mPrintButton.setImageResource(R.drawable.ic_menu_savetopdf);
             mPrintButton.setContentDescription(getString(R.string.savetopdf_button));
         }
-        if (!mPrintedDocument.getDocumentInfo().laidout
+        if (!mPrintedDocument.getDocumentInfo().updated
                 ||(mRangeOptionsSpinner.getSelectedItemPosition() == 1
                 && (TextUtils.isEmpty(mPageRangeEditText.getText()) || hasErrors()))
                 || (mRangeOptionsSpinner.getSelectedItemPosition() == 0
@@ -2048,7 +2041,6 @@
                 updateDocument(false);
             }
             ensurePreviewUiShown();
-            updateOptionsUi();
         }
     }
 
@@ -2058,7 +2050,6 @@
             mPrintedDocument.cancel(false);
             ensureErrorUiShown(getString(R.string.print_error_printer_unavailable),
                     PrintErrorFragment.ACTION_NONE);
-            updateOptionsUi();
         }
     }
 
@@ -3038,7 +3029,6 @@
             if (mState == STATE_UPDATE_SLOW) {
                 setState(STATE_UPDATE_SLOW);
                 ensureProgressUiShown();
-                updateOptionsUi();
 
                 return;
             } else if (mPosted) {
@@ -3080,7 +3070,6 @@
             mPreviousState = mState;
             setState(STATE_UPDATE_SLOW);
             ensureProgressUiShown();
-            updateOptionsUi();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index ebda2e8..ec80745 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -45,14 +45,12 @@
 import android.os.Messenger;
 import android.os.RemoteException;
 import android.util.Log;
-import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.WindowManager.LayoutParams;
-import android.view.accessibility.AccessibilityManager;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -61,6 +59,7 @@
 import com.android.systemui.R;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -128,8 +127,9 @@
                     break;
                 case MESSAGE_UPDATE_ACTIONS: {
                     final Bundle data = (Bundle) msg.obj;
-                    setActions(data.getParcelable(EXTRA_STACK_BOUNDS),
-                            ((ParceledListSlice) data.getParcelable(EXTRA_ACTIONS)).getList());
+                    final ParceledListSlice actions = data.getParcelable(EXTRA_ACTIONS);
+                    setActions(data.getParcelable(EXTRA_STACK_BOUNDS), actions != null
+                            ? actions.getList() : Collections.EMPTY_LIST);
                     break;
                 }
                 case MESSAGE_UPDATE_DISMISS_FRACTION: {
@@ -260,6 +260,7 @@
             }
             notifyMenuVisibility(true);
             updateExpandButtonFromBounds(stackBounds, movementBounds);
+            setDecorViewVisibility(true);
             mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
                     mMenuContainer.getAlpha(), 1f);
             mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
@@ -300,9 +301,7 @@
                     if (animationFinishedRunnable != null) {
                         animationFinishedRunnable.run();
                     }
-                    if (getSystemService(AccessibilityManager.class).isEnabled()) {
-                        finish();
-                    }
+                    setDecorViewVisibility(false);
                 }
             });
             mMenuContainerAnimator.addUpdateListener(mMenuBgUpdateListener);
@@ -411,6 +410,7 @@
     }
 
     private void updateDismissFraction(float fraction) {
+        setDecorViewVisibility(true);
         int alpha;
         if (mMenuVisible) {
             mMenuContainer.setAlpha(1-fraction);
@@ -497,4 +497,16 @@
         v.removeCallbacks(mFinishRunnable);
         v.postDelayed(mFinishRunnable, delay);
     }
+
+    /**
+     * Sets the visibility of the root view of the window to disable drawing and touches for the
+     * activity.  This differs from {@link Activity#setVisible(boolean)} in that it does not set
+     * the internal mVisibleFromClient state.
+     */
+    private void setDecorViewVisibility(boolean visible) {
+        final View decorView = getWindow().getDecorView();
+        if (decorView != null) {
+            decorView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/FontManagerService.java b/services/core/java/com/android/server/FontManagerService.java
index 55a945a..f172647 100644
--- a/services/core/java/com/android/server/FontManagerService.java
+++ b/services/core/java/com/android/server/FontManagerService.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.graphics.FontListParser;
+import android.net.Uri;
 import android.os.ParcelFileDescriptor;
 import android.text.FontConfig;
 import android.util.Slog;
@@ -34,6 +35,7 @@
 public class FontManagerService extends IFontManager.Stub {
     private static final String TAG = "FontManagerService";
     private static final String FONTS_CONFIG = "/system/etc/fonts.xml";
+    private static final String SYSTEM_FONT_DIR = "/system/fonts/";
 
     @GuardedBy("mLock")
     private FontConfig mConfig;
@@ -63,28 +65,22 @@
     public FontConfig getSystemFonts() {
         synchronized (mLock) {
             if (mConfig != null) {
-                return new FontConfig(mConfig);
+                return mConfig;
             }
 
-            FontConfig config = loadFromSystem();
-            if (config == null) {
+            mConfig = loadFromSystem();
+            if (mConfig == null) {
                 return null;
             }
 
-            for (FontConfig.Family family : config.getFamilies()) {
+            for (FontConfig.Family family : mConfig.getFamilies()) {
                 for (FontConfig.Font font : family.getFonts()) {
-                    File fontFile = new File(font.getFontName());
-                    try {
-                        font.setFd(ParcelFileDescriptor.open(
-                                fontFile, ParcelFileDescriptor.MODE_READ_ONLY));
-                    } catch (IOException e) {
-                        Slog.e(TAG, "Error opening font file " + font.getFontName(), e);
-                    }
+                    File fontFile = new File(SYSTEM_FONT_DIR, font.getFontName());
+                    font.setUri(Uri.fromFile(fontFile));
                 }
             }
 
-            mConfig = config;
-            return new FontConfig(mConfig);
+            return mConfig;
         }
     }
 
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 79be3e6..0ccaf8e 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -114,7 +114,6 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -201,7 +200,7 @@
         private final HashMap<Account, Integer> signinRequiredNotificationIds =
                 new HashMap<Account, Integer>();
         final Object cacheLock = new Object();
-        final Object dbLock = new Object();
+        final Object dbLock = new Object(); // if needed, dbLock must be obtained before cacheLock
         /** protected by the {@link #cacheLock} */
         final HashMap<String, Account[]> accountCache = new LinkedHashMap<>();
         /** protected by the {@link #cacheLock} */
@@ -586,13 +585,11 @@
      */
     private int getAccountVisibilityFromCache(Account account, String packageName,
             UserAccounts accounts) {
-        synchronized (accounts.dbLock) {
-            synchronized (accounts.cacheLock) {
-                Map<String, Integer> accountVisibility =
-                        getPackagesAndVisibilityForAccountLocked(account, accounts);
-                Integer visibility = accountVisibility.get(packageName);
-                return visibility != null ? visibility : AccountManager.VISIBILITY_UNDEFINED;
-            }
+        synchronized (accounts.cacheLock) {
+            Map<String, Integer> accountVisibility =
+                    getPackagesAndVisibilityForAccountLocked(account, accounts);
+            Integer visibility = accountVisibility.get(packageName);
+            return visibility != null ? visibility : AccountManager.VISIBILITY_UNDEFINED;
         }
     }
 
@@ -2240,16 +2237,23 @@
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
+            List<Pair<Account, String>> deletedTokens;
             synchronized (accounts.dbLock) {
+                accounts.accountsDb.beginTransaction();
+                try {
+                    deletedTokens = invalidateAuthTokenLocked(accounts, accountType, authToken);
+                    accounts.accountsDb.setTransactionSuccessful();
+                } finally {
+                    accounts.accountsDb.endTransaction();
+                }
                 synchronized (accounts.cacheLock) {
-                    accounts.accountsDb.beginTransaction();
-                    try {
-                        invalidateAuthTokenLocked(accounts, accountType, authToken);
-                        invalidateCustomTokenLocked(accounts, accountType, authToken);
-                        accounts.accountsDb.setTransactionSuccessful();
-                    } finally {
-                        accounts.accountsDb.endTransaction();
+                    for (Pair<Account, String> tokenInfo : deletedTokens) {
+                        Account act = tokenInfo.first;
+                        String tokenType = tokenInfo.second;
+                        writeAuthTokenIntoCacheLocked(accounts, act, tokenType, null);
                     }
+                    // wipe out cached token in memory.
+                    accounts.accountTokenCaches.remove(accountType, authToken);
                 }
             }
         } finally {
@@ -2257,38 +2261,24 @@
         }
     }
 
-    private void invalidateCustomTokenLocked(
-            UserAccounts accounts,
-            String accountType,
+    private List<Pair<Account, String>> invalidateAuthTokenLocked(UserAccounts accounts, String accountType,
             String authToken) {
-        if (authToken == null || accountType == null) {
-            return;
-        }
-        // Also wipe out cached token in memory.
-        accounts.accountTokenCaches.remove(accountType, authToken);
-    }
-
-    private void invalidateAuthTokenLocked(UserAccounts accounts, String accountType,
-            String authToken) {
-        if (authToken == null || accountType == null) {
-            return;
-        }
+        // TODO Move to AccountsDB
+        List<Pair<Account, String>> results = new ArrayList<>();
         Cursor cursor = accounts.accountsDb.findAuthtokenForAllAccounts(accountType, authToken);
+
         try {
             while (cursor.moveToNext()) {
                 String authTokenId = cursor.getString(0);
                 String accountName = cursor.getString(1);
                 String authTokenType = cursor.getString(2);
                 accounts.accountsDb.deleteAuthToken(authTokenId);
-                writeAuthTokenIntoCacheLocked(
-                        accounts,
-                        new Account(accountName, accountType),
-                        authTokenType,
-                        null);
+                results.add(Pair.create(new Account(accountName, accountType), authTokenType));
             }
         } finally {
             cursor.close();
         }
+        return results;
     }
 
     private void saveCachedToken(
@@ -2305,11 +2295,9 @@
         }
         cancelNotification(getSigninRequiredNotificationId(accounts, account),
                 UserHandle.of(accounts.userId));
-        synchronized (accounts.dbLock) {
-            synchronized (accounts.cacheLock) {
-                accounts.accountTokenCaches.put(
-                        account, token, tokenType, callerPkg, callerSigDigest, expiryMillis);
-            }
+        synchronized (accounts.cacheLock) {
+            accounts.accountTokenCaches.put(
+                    account, token, tokenType, callerPkg, callerSigDigest, expiryMillis);
         }
     }
 
@@ -2321,22 +2309,26 @@
         cancelNotification(getSigninRequiredNotificationId(accounts, account),
                 UserHandle.of(accounts.userId));
         synchronized (accounts.dbLock) {
-            synchronized (accounts.cacheLock) {
-                accounts.accountsDb.beginTransaction();
-                try {
-                    long accountId = accounts.accountsDb.findDeAccountId(account);
-                    if (accountId < 0) {
-                        return false;
-                    }
-                    accounts.accountsDb.deleteAuthtokensByAccountIdAndType(accountId, type);
-                    if (accounts.accountsDb.insertAuthToken(accountId, type, authToken) >= 0) {
-                        accounts.accountsDb.setTransactionSuccessful();
-                        writeAuthTokenIntoCacheLocked(accounts, account, type, authToken);
-                        return true;
-                    }
+            accounts.accountsDb.beginTransaction();
+            boolean updateCache = false;
+            try {
+                long accountId = accounts.accountsDb.findDeAccountId(account);
+                if (accountId < 0) {
                     return false;
-                } finally {
-                    accounts.accountsDb.endTransaction();
+                }
+                accounts.accountsDb.deleteAuthtokensByAccountIdAndType(accountId, type);
+                if (accounts.accountsDb.insertAuthToken(accountId, type, authToken) >= 0) {
+                    accounts.accountsDb.setTransactionSuccessful();
+                    updateCache = true;
+                    return true;
+                }
+                return false;
+            } finally {
+                accounts.accountsDb.endTransaction();
+                if (updateCache) {
+                    synchronized (accounts.cacheLock) {
+                        writeAuthTokenIntoCacheLocked(accounts, account, type, authToken);
+                    }
                 }
             }
         }
@@ -3947,13 +3939,8 @@
 
         @Override
         public void run() throws RemoteException {
-            synchronized (mAccounts.dbLock) {
-                synchronized (mAccounts.cacheLock) {
-                    mAccountsOfType = getAccountsFromCacheLocked(mAccounts, mAccountType,
-                            mCallingUid,
-                            mPackageName, false /* include managed not visible*/);
-                }
-            }
+            mAccountsOfType = getAccountsFromCache(mAccounts, mAccountType,
+                    mCallingUid, mPackageName, false /* include managed not visible*/);
             // check whether each account matches the requested features
             mAccountsWithFeatures = new ArrayList<>(mAccountsOfType.length);
             mCurrentAccount = 0;
@@ -4097,18 +4084,14 @@
         for (int userId : userIds) {
             UserAccounts userAccounts = getUserAccounts(userId);
             if (userAccounts == null) continue;
-            synchronized (userAccounts.dbLock) {
-                synchronized (userAccounts.cacheLock) {
-                    Account[] accounts = getAccountsFromCacheLocked(
-                            userAccounts,
-                            null /* type */,
-                            Binder.getCallingUid(),
-                            null /* packageName */,
-                            false /* include managed not visible*/);
-                    for (int a = 0; a < accounts.length; a++) {
-                        runningAccounts.add(new AccountAndUser(accounts[a], userId));
-                    }
-                }
+            Account[] accounts = getAccountsFromCache(
+                    userAccounts,
+                    null /* type */,
+                    Binder.getCallingUid(),
+                    null /* packageName */,
+                    false /* include managed not visible*/);
+            for (Account account : accounts) {
+                runningAccounts.add(new AccountAndUser(account, userId));
             }
         }
 
@@ -4194,24 +4177,20 @@
             String callingPackage,
             List<String> visibleAccountTypes,
             boolean includeUserManagedNotVisible) {
-        synchronized (userAccounts.dbLock) {
-            synchronized (userAccounts.cacheLock) {
-                ArrayList<Account> visibleAccounts = new ArrayList<>();
-                for (String visibleType : visibleAccountTypes) {
-                    Account[] accountsForType = getAccountsFromCacheLocked(
-                            userAccounts, visibleType, callingUid, callingPackage,
-                            includeUserManagedNotVisible);
-                    if (accountsForType != null) {
-                        visibleAccounts.addAll(Arrays.asList(accountsForType));
-                    }
-                }
-                Account[] result = new Account[visibleAccounts.size()];
-                for (int i = 0; i < visibleAccounts.size(); i++) {
-                    result[i] = visibleAccounts.get(i);
-                }
-                return result;
+        ArrayList<Account> visibleAccounts = new ArrayList<>();
+        for (String visibleType : visibleAccountTypes) {
+            Account[] accountsForType = getAccountsFromCache(
+                    userAccounts, visibleType, callingUid, callingPackage,
+                    includeUserManagedNotVisible);
+            if (accountsForType != null) {
+                visibleAccounts.addAll(Arrays.asList(accountsForType));
             }
         }
+        Account[] result = new Account[visibleAccounts.size()];
+        for (int i = 0; i < visibleAccounts.size(); i++) {
+            result[i] = visibleAccounts.get(i);
+        }
+        return result;
     }
 
     @Override
@@ -4277,10 +4256,12 @@
     public Account[] getSharedAccountsAsUser(int userId) {
         userId = handleIncomingUser(userId);
         UserAccounts accounts = getUserAccounts(userId);
-        List<Account> accountList = accounts.accountsDb.getSharedAccounts();
-        Account[] accountArray = new Account[accountList.size()];
-        accountList.toArray(accountArray);
-        return accountArray;
+        synchronized (accounts.dbLock) {
+            List<Account> accountList = accounts.accountsDb.getSharedAccounts();
+            Account[] accountArray = new Account[accountList.size()];
+            accountList.toArray(accountArray);
+            return accountArray;
+        }
     }
 
     @Override
@@ -4360,13 +4341,8 @@
         try {
             UserAccounts userAccounts = getUserAccounts(userId);
             if (features == null || features.length == 0) {
-                Account[] accounts;
-                synchronized (userAccounts.dbLock) {
-                    synchronized (userAccounts.cacheLock) {
-                        accounts = getAccountsFromCacheLocked(
-                                userAccounts, type, callingUid, opPackageName, false);
-                    }
-                }
+                Account[] accounts = getAccountsFromCache(userAccounts, type, callingUid,
+                        opPackageName, false);
                 Bundle result = new Bundle();
                 result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts);
                 onResult(response, result);
@@ -4922,36 +4898,36 @@
 
     private void dumpUser(UserAccounts userAccounts, FileDescriptor fd, PrintWriter fout,
             String[] args, boolean isCheckinRequest) {
-        synchronized (userAccounts.dbLock) {
-            synchronized (userAccounts.cacheLock) {
-                if (isCheckinRequest) {
-                    // This is a checkin request. *Only* upload the account types and the count of
-                    // each.
-                    userAccounts.accountsDb.dumpDeAccountsTable(fout);
-                } else {
-                    Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */,
-                            Process.SYSTEM_UID, null /* packageName */, false);
-                    fout.println("Accounts: " + accounts.length);
-                    for (Account account : accounts) {
-                        fout.println("  " + account);
-                    }
+        if (isCheckinRequest) {
+            // This is a checkin request. *Only* upload the account types and the count of
+            // each.
+            synchronized (userAccounts.dbLock) {
+                userAccounts.accountsDb.dumpDeAccountsTable(fout);
+            }
+        } else {
+            Account[] accounts = getAccountsFromCache(userAccounts, null /* type */,
+                    Process.SYSTEM_UID, null /* packageName */, false);
+            fout.println("Accounts: " + accounts.length);
+            for (Account account : accounts) {
+                fout.println("  " + account);
+            }
 
-                    // Add debug information.
-                    fout.println();
-                    userAccounts.accountsDb.dumpDebugTable(fout);
-                    fout.println();
-                    synchronized (mSessions) {
-                        final long now = SystemClock.elapsedRealtime();
-                        fout.println("Active Sessions: " + mSessions.size());
-                        for (Session session : mSessions.values()) {
-                            fout.println("  " + session.toDebugString(now));
-                        }
-                    }
-
-                    fout.println();
-                    mAuthenticatorCache.dump(fd, fout, args, userAccounts.userId);
+            // Add debug information.
+            fout.println();
+            synchronized (userAccounts.dbLock) {
+                userAccounts.accountsDb.dumpDebugTable(fout);
+            }
+            fout.println();
+            synchronized (mSessions) {
+                final long now = SystemClock.elapsedRealtime();
+                fout.println("Active Sessions: " + mSessions.size());
+                for (Session session : mSessions.values()) {
+                    fout.println("  " + session.toDebugString(now));
                 }
             }
+
+            fout.println();
+            mAuthenticatorCache.dump(fd, fout, args, userAccounts.userId);
         }
     }
 
@@ -5609,12 +5585,20 @@
     /*
      * packageName can be null. If not null, it should be used to filter out restricted accounts
      * that the package is not allowed to access.
+     *
+     * <p>The method shouldn't be called with UserAccounts#cacheLock held, otherwise it will cause a
+     * deadlock
      */
     @NonNull
-    protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType,
+    protected Account[] getAccountsFromCache(UserAccounts userAccounts, String accountType,
             int callingUid, @Nullable String callingPackage, boolean includeManagedNotVisible) {
+        Preconditions.checkState(!Thread.holdsLock(userAccounts.cacheLock),
+                "Method should not be called with cacheLock");
         if (accountType != null) {
-            final Account[] accounts = userAccounts.accountCache.get(accountType);
+            Account[] accounts;
+            synchronized (userAccounts.cacheLock) {
+                accounts = userAccounts.accountCache.get(accountType);
+            }
             if (accounts == null) {
                 return EMPTY_ACCOUNT_ARRAY;
             } else {
@@ -5623,20 +5607,23 @@
             }
         } else {
             int totalLength = 0;
-            for (Account[] accounts : userAccounts.accountCache.values()) {
-                totalLength += accounts.length;
+            Account[] accountsArray;
+            synchronized (userAccounts.cacheLock) {
+                for (Account[] accounts : userAccounts.accountCache.values()) {
+                    totalLength += accounts.length;
+                }
+                if (totalLength == 0) {
+                    return EMPTY_ACCOUNT_ARRAY;
+                }
+                accountsArray = new Account[totalLength];
+                totalLength = 0;
+                for (Account[] accountsOfType : userAccounts.accountCache.values()) {
+                    System.arraycopy(accountsOfType, 0, accountsArray, totalLength,
+                            accountsOfType.length);
+                    totalLength += accountsOfType.length;
+                }
             }
-            if (totalLength == 0) {
-                return EMPTY_ACCOUNT_ARRAY;
-            }
-            Account[] accounts = new Account[totalLength];
-            totalLength = 0;
-            for (Account[] accountsOfType : userAccounts.accountCache.values()) {
-                System.arraycopy(accountsOfType, 0, accounts, totalLength,
-                        accountsOfType.length);
-                totalLength += accountsOfType.length;
-            }
-            return filterAccounts(userAccounts, accounts, callingUid, callingPackage,
+            return filterAccounts(userAccounts, accountsArray, callingUid, callingPackage,
                     includeManagedNotVisible);
         }
     }
@@ -5669,6 +5656,7 @@
         }
     }
 
+    /** protected by the {@code dbLock}, {@code cacheLock} */
     protected void writeAuthTokenIntoCacheLocked(UserAccounts accounts,
             Account account, String key, String value) {
         Map<String, String> authTokensForAccount = accounts.authTokenCache.get(account);
@@ -5685,6 +5673,14 @@
 
     protected String readAuthTokenInternal(UserAccounts accounts, Account account,
             String authTokenType) {
+        // Fast path - check if account is already cached
+        synchronized (accounts.cacheLock) {
+            Map<String, String> authTokensForAccount = accounts.authTokenCache.get(account);
+            if (authTokensForAccount != null) {
+                return authTokensForAccount.get(authTokenType);
+            }
+        }
+        // If not cached yet - do slow path and sync with db if necessary
         synchronized (accounts.dbLock) {
             synchronized (accounts.cacheLock) {
                 Map<String, String> authTokensForAccount = accounts.authTokenCache.get(account);
diff --git a/services/core/java/com/android/server/fingerprint/EnumerateClient.java b/services/core/java/com/android/server/fingerprint/EnumerateClient.java
index 1b8b89c..34f245f 100644
--- a/services/core/java/com/android/server/fingerprint/EnumerateClient.java
+++ b/services/core/java/com/android/server/fingerprint/EnumerateClient.java
@@ -58,7 +58,7 @@
     public int stop(boolean initiatedByClient) {
         IBiometricsFingerprint daemon = getFingerprintDaemon();
         if (daemon == null) {
-            Slog.w(TAG, "stopEnumeration: no fingerprint HAL!");
+            Slog.w(TAG, "stopAuthentication: no fingerprint HAL!");
             return ERROR_ESRCH;
         }
         try {
@@ -102,12 +102,12 @@
     @Override
     public boolean onEnrollResult(int fingerId, int groupId, int rem) {
         if (DEBUG) Slog.w(TAG, "onEnrollResult() called for enumerate!");
-        return true; // Invalid for Enumerate.
+        return true; // Invalid for Remove
     }
 
     @Override
     public boolean onRemoved(int fingerId, int groupId, int remaining) {
         if (DEBUG) Slog.w(TAG, "onRemoved() called for enumerate!");
-        return true; // Invalid for Enumerate.
+        return true; // Invalid for Authenticate
     }
 }
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index b6e7932..7d97ce4 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -85,7 +85,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.LinkedList;
 
 /**
  * A service to manage multiple clients that want to access the fingerprint HAL API.
@@ -135,20 +134,6 @@
     private ClientMonitor mPendingClient;
     private PerformanceStats mPerformanceStats;
 
-
-    private IBinder mToken = new Binder(); // used for internal FingerprintService enumeration
-    private LinkedList<Integer> mEnumeratingUserIds = new LinkedList<>();
-    private ArrayList<UserFingerprint> mUnknownFingerprints = new ArrayList<>(); // hw finterprints
-
-    private class UserFingerprint {
-        Fingerprint f;
-        int userId;
-        public UserFingerprint(Fingerprint f, int userId) {
-            this.f = f;
-            this.userId = userId;
-        }
-    }
-
     // Normal fingerprint authentications are tracked by mPerformanceMap.
     private HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>();
 
@@ -272,12 +257,10 @@
         // This operation can be expensive, so keep track of the elapsed time. Might need to move to
         // background if it takes too long.
         long t = System.currentTimeMillis();
+
         mAuthenticatorIds.clear();
-        mEnumeratingUserIds.clear();
-        mUnknownFingerprints.clear();
         for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
             int userId = getUserOrWorkProfileId(null, user.id);
-            mEnumeratingUserIds.add(userId);
             if (!mAuthenticatorIds.containsKey(userId)) {
                 updateActiveGroup(userId, null);
             }
@@ -287,70 +270,12 @@
         if (t > 1000) {
             Slog.w(TAG, "loadAuthenticatorIds() taking too long: " + t + "ms");
         }
-
-        if (!mEnumeratingUserIds.isEmpty()) {
-            enumerateNextUser();
-        }
-    }
-
-    private void enumerateNextUser() {
-        int nextUser = mEnumeratingUserIds.getFirst();
-        updateActiveGroup(nextUser, null);
-        boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
-
-        if (DEBUG) Slog.v(TAG, "Enumerating user id " + nextUser + " of "
-                + mEnumeratingUserIds.size() + " remaining users");
-
-        startEnumerate(mToken, nextUser, null, restricted, true /* internal */);
-    }
-
-    // Remove unknown fingerprints from hardware
-    private void cleanupUnknownFingerprints() {
-        if (!mUnknownFingerprints.isEmpty()) {
-            Slog.w(TAG, "unknown fingerprint size: " + mUnknownFingerprints.size());
-            UserFingerprint uf = mUnknownFingerprints.get(0);
-            mUnknownFingerprints.remove(uf);
-            boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
-            updateActiveGroup(uf.userId, null);
-            startRemove(mToken, uf.f.getFingerId(), uf.f.getGroupId(), uf.userId, null,
-                    restricted, true /* internal */);
-        }
     }
 
     protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) {
-        if (DEBUG) Slog.w(TAG, "Enumerate: fid=" + fingerId
-                + ", gid=" + groupId
-                + ", dev=" + deviceId
-                + ", rem=" + remaining);
-
-        ClientMonitor client = mCurrentClient;
-
-        if (client != null) {
-            client.onEnumerationResult(fingerId, groupId, remaining);
-        }
-
-        // All fingerprints in hardware for this user were enumerated
-        if (remaining == 0) {
-            mEnumeratingUserIds.poll();
-
-            if (client instanceof InternalEnumerateClient) {
-                List<Fingerprint> enrolled = ((InternalEnumerateClient) client).getEnumeratedList();
-                Slog.w(TAG, "Added " + enrolled.size() + " enumerated fingerprints for deletion");
-                for (Fingerprint f : enrolled) {
-                    mUnknownFingerprints.add(new UserFingerprint(f, client.getTargetUserId()));
-                }
-            }
-
-            removeClient(client);
-
-            if (!mEnumeratingUserIds.isEmpty()) {
-                enumerateNextUser();
-            } else if (client instanceof InternalEnumerateClient) {
-                if (DEBUG) Slog.v(TAG, "Finished enumerating all users");
-                // This will start a chain of InternalRemovalClients
-                cleanupUnknownFingerprints();
-            }
-        }
+        if (DEBUG) Slog.w(TAG, "Enumerate: fid=" + fingerId + ", gid="
+                + groupId + "rem=" + remaining);
+        // TODO: coordinate names with framework
     }
 
     protected void handleError(long deviceId, int error, int vendorCode) {
@@ -379,18 +304,10 @@
     }
 
     protected void handleRemoved(long deviceId, int fingerId, int groupId, int remaining) {
-        if (DEBUG) Slog.w(TAG, "Removed: fid=" + fingerId
-                + ", gid=" + groupId
-                + ", dev=" + deviceId
-                + ", rem=" + remaining);
-
         ClientMonitor client = mCurrentClient;
         if (client != null && client.onRemoved(fingerId, groupId, remaining)) {
             removeClient(client);
         }
-        if (client instanceof InternalRemovalClient && !mUnknownFingerprints.isEmpty()) {
-            cleanupUnknownFingerprints();
-        }
     }
 
     protected void handleAuthenticated(long deviceId, int fingerId, int groupId,
@@ -517,15 +434,7 @@
         ClientMonitor currentClient = mCurrentClient;
         if (currentClient != null) {
             if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString());
-            if (currentClient instanceof InternalEnumerateClient ||
-                    currentClient instanceof InternalRemovalClient) {
-                // This condition means we're currently running internal diagnostics to
-                // remove extra fingerprints in the hardware and/or the software
-                // TODO: design an escape hatch in case client never finishes
-            }
-            else {
-                currentClient.stop(initiatedByClient);
-            }
+            currentClient.stop(initiatedByClient);
             mPendingClient = newClient;
             mHandler.removeCallbacks(mResetClientState);
             mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
@@ -542,86 +451,47 @@
     }
 
     void startRemove(IBinder token, int fingerId, int groupId, int userId,
-            IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
+            IFingerprintServiceReceiver receiver, boolean restricted) {
         IBiometricsFingerprint daemon = getFingerprintDaemon();
         if (daemon == null) {
             Slog.w(TAG, "startRemove: no fingerprint HAL!");
             return;
         }
+        RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token,
+                receiver, fingerId, groupId, userId, restricted, token.toString()) {
+            @Override
+            public void notifyUserActivity() {
+                FingerprintService.this.userActivity();
+            }
 
-        if (internal) {
-            Context context = getContext();
-            InternalRemovalClient client = new InternalRemovalClient(context, mHalDeviceId,
-                    token, receiver, fingerId, groupId, userId, restricted,
-                    context.getOpPackageName()) {
-                @Override
-                public void notifyUserActivity() {
-
-                }
-                @Override
-                public IBiometricsFingerprint getFingerprintDaemon() {
-                    return FingerprintService.this.getFingerprintDaemon();
-                }
-            };
-            startClient(client, true);
-        }
-        else {
-            RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token,
-                    receiver, fingerId, groupId, userId, restricted, token.toString()) {
-                @Override
-                public void notifyUserActivity() {
-                    FingerprintService.this.userActivity();
-                }
-
-                @Override
-                public IBiometricsFingerprint getFingerprintDaemon() {
-                    return FingerprintService.this.getFingerprintDaemon();
-                }
-            };
-            startClient(client, true);
-        }
+            @Override
+            public IBiometricsFingerprint getFingerprintDaemon() {
+                return FingerprintService.this.getFingerprintDaemon();
+            }
+        };
+        startClient(client, true);
     }
 
     void startEnumerate(IBinder token, int userId,
-        IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
+        IFingerprintServiceReceiver receiver, boolean restricted) {
         IBiometricsFingerprint daemon = getFingerprintDaemon();
         if (daemon == null) {
             Slog.w(TAG, "startEnumerate: no fingerprint HAL!");
             return;
         }
-        if (internal) {
-            List<Fingerprint> enrolledList = getEnrolledFingerprints(userId);
-            Context context = getContext();
-            InternalEnumerateClient client = new InternalEnumerateClient(context, mHalDeviceId,
-                    token, receiver, userId, userId, restricted, context.getOpPackageName(),
-                    enrolledList) {
-                @Override
-                public void notifyUserActivity() {
+        EnumerateClient client = new EnumerateClient(getContext(), mHalDeviceId, token,
+            receiver, userId, userId, restricted, token.toString()) {
+            @Override
+            public void notifyUserActivity() {
+                FingerprintService.this.userActivity();
+            }
 
-                }
-
-                @Override
-                public IBiometricsFingerprint getFingerprintDaemon() {
-                    return FingerprintService.this.getFingerprintDaemon();
-                }
-            };
-            startClient(client, true);
-        }
-        else {
-            EnumerateClient client = new EnumerateClient(getContext(), mHalDeviceId, token,
-                    receiver, userId, userId, restricted, token.toString()) {
-                @Override
-                public void notifyUserActivity() {
-                    FingerprintService.this.userActivity();
-                }
-
-                @Override
-                public IBiometricsFingerprint getFingerprintDaemon() {
-                    return FingerprintService.this.getFingerprintDaemon();
-                }
-            };
-            startClient(client, true);
-        }
+            @Override
+            public IBiometricsFingerprint getFingerprintDaemon() {
+                return FingerprintService.this.getFingerprintDaemon();
+            }
+        };
+        startClient(client, true);
     }
 
     public List<Fingerprint> getEnrolledFingerprints(int userId) {
@@ -1108,14 +978,12 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    startRemove(token, fingerId, groupId, userId, receiver,
-                            restricted, false /* internal */);
+                    startRemove(token, fingerId, groupId, userId, receiver, restricted);
                 }
             });
 
         }
 
-        @Override // Binder call
         public void enumerate(final IBinder token, final int userId,
             final IFingerprintServiceReceiver receiver) {
             checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
@@ -1123,7 +991,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    startEnumerate(token, userId, receiver, restricted, false /* internal */);
+                    startEnumerate(token, userId, receiver, restricted);
                 }
             });
 
diff --git a/services/core/java/com/android/server/fingerprint/InternalEnumerateClient.java b/services/core/java/com/android/server/fingerprint/InternalEnumerateClient.java
deleted file mode 100644
index f4d2596..0000000
--- a/services/core/java/com/android/server/fingerprint/InternalEnumerateClient.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 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
- */
-
-package com.android.server.fingerprint;
-
-import android.content.Context;
-import android.hardware.fingerprint.Fingerprint;
-import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.os.IBinder;
-import android.util.Slog;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * An internal class to help clean up unknown fingerprints in the hardware and software
- */
-public abstract class InternalEnumerateClient extends EnumerateClient {
-
-    private List<Fingerprint> mEnrolledList;
-    private List<Fingerprint> mEnumeratedList = new ArrayList<>(); // list of fp to delete
-
-    public InternalEnumerateClient(Context context, long halDeviceId, IBinder token,
-            IFingerprintServiceReceiver receiver, int groupId, int userId,
-            boolean restricted, String owner, List<Fingerprint> enrolledList) {
-
-        super(context, halDeviceId, token, receiver, userId, groupId, restricted, owner);
-        mEnrolledList = enrolledList;
-    }
-
-    private void handleEnumeratedFingerprint(int fingerId, int groupId, int remaining) {
-
-        boolean matched = false;
-        for (int i=0; i<mEnrolledList.size(); i++) {
-            if (mEnrolledList.get(i).getFingerId() == fingerId) {
-                mEnrolledList.remove(i);
-                matched = true;
-                Slog.e(TAG, "Matched fingerprint fid=" + fingerId);
-                break;
-            }
-        }
-
-        // fingerId 0 means no fingerprints are in hardware
-        if (!matched && fingerId != 0) {
-            Fingerprint fingerprint = new Fingerprint("", groupId, fingerId, getHalDeviceId());
-            mEnumeratedList.add(fingerprint);
-        }
-    }
-
-    private void doFingerprintCleanup() {
-
-        if (mEnrolledList == null) {
-            return;
-        }
-
-        for (Fingerprint f : mEnrolledList) {
-            Slog.e(TAG, "Internal Enumerate: Removing dangling enrolled fingerprint: "
-                    + f.getName() + " " + f.getFingerId() + " " + f.getGroupId()
-                    + " " + f.getDeviceId());
-
-            FingerprintUtils.getInstance().removeFingerprintIdForUser(getContext(),
-                    f.getFingerId(), getTargetUserId());
-        }
-        mEnrolledList.clear();
-    }
-
-    public List<Fingerprint> getEnumeratedList() {
-        return mEnumeratedList;
-    }
-
-    @Override
-    public boolean onEnumerationResult(int fingerId, int groupId, int remaining) {
-
-        handleEnumeratedFingerprint(fingerId, groupId, remaining);
-        if (remaining == 0) {
-            doFingerprintCleanup();
-        }
-
-        return fingerId == 0; // done when id hits 0
-    }
-
-}
diff --git a/services/core/java/com/android/server/fingerprint/InternalRemovalClient.java b/services/core/java/com/android/server/fingerprint/InternalRemovalClient.java
deleted file mode 100644
index 19f61fe..0000000
--- a/services/core/java/com/android/server/fingerprint/InternalRemovalClient.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 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
- */
-
-package com.android.server.fingerprint;
-
-import android.content.Context;
-import android.os.IBinder;
-import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import com.android.server.fingerprint.RemovalClient;
-
-public abstract class InternalRemovalClient extends RemovalClient {
-
-    public InternalRemovalClient(Context context, long halDeviceId, IBinder token,
-            IFingerprintServiceReceiver receiver, int fingerId, int groupId, int userId,
-            boolean restricted, String owner) {
-
-        super(context, halDeviceId, token, receiver, fingerId, groupId, userId, restricted, owner);
-
-    }
-}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index da9aa06..afee290 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -336,12 +336,12 @@
 
     /**
      * Indicates venue name (such as 'San Francisco Airport') published by access point; only
-     * available on passpoint network and if published by access point.
+     * available on Passpoint network and if published by access point.
      */
     public CharSequence venueName;
 
     /**
-     * Indicates passpoint operator name published by access point.
+     * Indicates Passpoint operator name published by access point.
      */
     public CharSequence operatorFriendlyName;
 
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 04f9059..7defa7c 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -367,12 +367,12 @@
     public WifiEnterpriseConfig enterpriseConfig;
 
     /**
-     * Fully qualified domain name of a passpoint configuration
+     * Fully qualified domain name of a Passpoint configuration
      */
     public String FQDN;
 
     /**
-     * Name of passpoint credential provider
+     * Name of Passpoint credential provider
      */
     public String providerFriendlyName;
 
@@ -385,8 +385,8 @@
     public boolean isHomeProviderNetwork;
 
     /**
-     * Roaming Consortium Id list for passpoint credential; identifies a set of networks where
-     * passpoint credential will be considered valid
+     * Roaming Consortium Id list for Passpoint credential; identifies a set of networks where
+     * Passpoint credential will be considered valid
      */
     public long[] roamingConsortiumIds;
 
@@ -1425,7 +1425,7 @@
     }
 
     /**
-     * Identify if this configuration represents a passpoint network
+     * Identify if this configuration represents a Passpoint network
      */
     public boolean isPasspoint() {
         return !TextUtils.isEmpty(FQDN)
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 4268f24..18f30f8 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -940,8 +940,8 @@
     }
 
     /**
-     * Set realm for passpoint credential; realm identifies a set of networks where your
-     * passpoint credential can be used
+     * Set realm for Passpoint credential; realm identifies a set of networks where your
+     * Passpoint credential can be used
      * @param realm the realm
      */
     public void setRealm(String realm) {
@@ -949,7 +949,7 @@
     }
 
     /**
-     * Get realm for passpoint credential; see {@link #setRealm(String)} for more information
+     * Get realm for Passpoint credential; see {@link #setRealm(String)} for more information
      * @return the realm
      */
     public String getRealm() {
@@ -957,7 +957,7 @@
     }
 
     /**
-     * Set plmn (Public Land Mobile Network) of the provider of passpoint credential
+     * Set plmn (Public Land Mobile Network) of the provider of Passpoint credential
      * @param plmn the plmn value derived from mcc (mobile country code) & mnc (mobile network code)
      */
     public void setPlmn(String plmn) {
@@ -965,7 +965,7 @@
     }
 
     /**
-     * Get plmn (Public Land Mobile Network) for passpoint credential; see {@link #setPlmn
+     * Get plmn (Public Land Mobile Network) for Passpoint credential; see {@link #setPlmn
      * (String)} for more information
      * @return the plmn
      */
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index ae6a679..9ee772a 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -858,6 +858,10 @@
 
     /**
      * Returns a WifiConfiguration matching this ScanResult
+     *
+     * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled
+     * on the device.
+     *
      * @param scanResult scanResult that represents the BSSID
      * @return {@link WifiConfiguration} that matches this BSSID or null
      * @hide
@@ -944,6 +948,8 @@
      * FQDN, the new configuration will replace the existing configuration.
      *
      * An {@link IllegalArgumentException} will be thrown on failure.
+     * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled
+     * on the device.
      *
      * @param config The Passpoint configuration to be added
      */
@@ -961,8 +967,10 @@
      * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name).
      *
      * An {@link IllegalArgumentException} will be thrown on failure.
+     * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled
+     * on the device.
      *
-     * @param fqdn The FQDN of the passpoint configuration to be removed
+     * @param fqdn The FQDN of the Passpoint configuration to be removed
      */
     public void removePasspointConfiguration(String fqdn) {
         try {
@@ -979,6 +987,9 @@
      *
      * An empty list will be returned when no configurations are installed.
      *
+     * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled
+     * on the device.
+     *
      * @return A list of {@link PasspointConfiguration}
      */
     public List<PasspointConfiguration> getPasspointConfigurations() {
@@ -995,6 +1006,9 @@
      * {@link #EXTRA_ICON} will indicate the result of the request.
      * A missing intent extra {@link #EXTRA_ICON} will indicate a failure.
      *
+     * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled
+     * on the device.
+     *
      * @param bssid The BSSID of the AP
      * @param fileName Name of the icon file (remote file) to query from the AP
      */
@@ -1254,7 +1268,7 @@
     }
 
     /**
-     * @return true if this adapter supports passpoint
+     * @return true if this adapter supports Passpoint
      * @hide
      */
     public boolean isPasspointSupported() {
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index eceb365..4387b0c 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -18,11 +18,10 @@
 
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -140,8 +139,8 @@
 
         // (1) connect + success
         mDut.attach(mockCallback, mMockLooperHandler);
-        inOrder.verify(mockAwareService).connect(binder.capture(), anyString(),
-                clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+        inOrder.verify(mockAwareService).connect(binder.capture(), any(),
+                clientProxyCallback.capture(), isNull(), eq(false));
         clientProxyCallback.getValue().onConnectSuccess(clientId);
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -150,8 +149,7 @@
         // (2) publish - should succeed
         PublishConfig publishConfig = new PublishConfig.Builder().build();
         session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
-        inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
-                any(IWifiAwareDiscoverySessionCallback.class));
+        inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig), any());
 
         // (3) disconnect
         session.destroy();
@@ -163,8 +161,8 @@
 
         // (5) connect
         mDut.attach(mockCallback, mMockLooperHandler);
-        inOrder.verify(mockAwareService).connect(binder.capture(), anyString(),
-                any(IWifiAwareEventCallback.class), (ConfigRequest) isNull(), eq(false));
+        inOrder.verify(mockAwareService).connect(binder.capture(), any(), any(), isNull(),
+                eq(false));
 
         verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService);
     }
@@ -185,16 +183,16 @@
 
         // (1) connect + failure
         mDut.attach(mockCallback, mMockLooperHandler);
-        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
-                clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+        inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+                isNull(), eq(false));
         clientProxyCallback.getValue().onConnectFail(reason);
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onAttachFailed();
 
         // (2) connect + success
         mDut.attach(mockCallback, mMockLooperHandler);
-        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
-                clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+        inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+                isNull(), eq(false));
         clientProxyCallback.getValue().onConnectSuccess(clientId);
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -203,8 +201,7 @@
         // (4) subscribe: should succeed
         SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
         session.subscribe(subscribeConfig, mockSessionCallback, mMockLooperHandler);
-        inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig),
-                any(IWifiAwareDiscoverySessionCallback.class));
+        inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig), any());
 
         verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService);
     }
@@ -223,19 +220,19 @@
 
         // (1) connect + success
         mDut.attach(mockCallback, mMockLooperHandler);
-        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
-                clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+        inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+                isNull(), eq(false));
         clientProxyCallback.getValue().onConnectSuccess(clientId);
         mMockLooper.dispatchAll();
-        inOrder.verify(mockCallback).onAttached(any(WifiAwareSession.class));
+        inOrder.verify(mockCallback).onAttached(any());
 
         // (2) connect + success
         mDut.attach(mockCallback, mMockLooperHandler);
-        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
-                clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+        inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+                isNull(), eq(false));
         clientProxyCallback.getValue().onConnectSuccess(clientId + 1);
         mMockLooper.dispatchAll();
-        inOrder.verify(mockCallback).onAttached(any(WifiAwareSession.class));
+        inOrder.verify(mockCallback).onAttached(any());
 
         verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService);
     }
@@ -278,8 +275,8 @@
 
         // (0) connect + success
         mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
-        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
-                clientProxyCallback.capture(), eq(configRequest), eq(false));
+        inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+                eq(configRequest), eq(false));
         clientProxyCallback.getValue().onConnectSuccess(clientId);
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -370,8 +367,8 @@
 
         // (1) connect successfully
         mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
-        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
-                clientProxyCallback.capture(), eq(configRequest), eq(false));
+        inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+                eq(configRequest), eq(false));
         clientProxyCallback.getValue().onConnectSuccess(clientId);
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -426,8 +423,8 @@
 
         // (0) connect + success
         mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
-        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
-                clientProxyCallback.capture(), eq(configRequest), eq(false));
+        inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+                eq(configRequest), eq(false));
         clientProxyCallback.getValue().onConnectSuccess(clientId);
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -507,8 +504,8 @@
 
         // (1) connect successfully
         mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
-        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
-                clientProxyCallback.capture(), eq(configRequest), eq(false));
+        inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+                eq(configRequest), eq(false));
         clientProxyCallback.getValue().onConnectSuccess(clientId);
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -899,8 +896,7 @@
         final RttManager.RttResult rttResults = new RttManager.RttResult();
         rttResults.distance = 10;
 
-        when(mockAwareService.startRanging(anyInt(), anyInt(),
-                any(RttManager.ParcelableRttParams.class))).thenReturn(rangingId);
+        when(mockAwareService.startRanging(anyInt(), anyInt(), any())).thenReturn(rangingId);
 
         InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
                 mockPublishSession, mockRttListener);
@@ -919,8 +915,8 @@
 
         // (1) connect successfully
         mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
-        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
-                clientProxyCallback.capture(), eq(configRequest), eq(false));
+        inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+                eq(configRequest), eq(false));
         clientProxyCallback.getValue().onConnectSuccess(clientId);
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -994,8 +990,8 @@
 
         // (1) connect successfully
         mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
-        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
-                clientProxyCallback.capture(), eq(configRequest), eq(false));
+        inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+                eq(configRequest), eq(false));
         clientProxyCallback.getValue().onConnectSuccess(clientId);
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -1085,8 +1081,8 @@
 
         // (1) connect successfully
         mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
-        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
-                clientProxyCallback.capture(), eq(configRequest), eq(false));
+        inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+                eq(configRequest), eq(false));
         clientProxyCallback.getValue().onConnectSuccess(clientId);
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());