Merge "Metrics constants for new screen" into qt-dev
diff --git a/api/test-current.txt b/api/test-current.txt
index 62d8b20..95f4a2e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3391,6 +3391,7 @@
 package android.view.inputmethod {
 
   public final class InputMethodManager {
+    method public int getDisplayId();
     method public boolean isInputMethodPickerShown();
   }
 
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index b44458a..cc5d3b1 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -419,26 +419,36 @@
         Preconditions.checkNotNull(cr);
         Preconditions.checkNotNull(notifyUris);
 
-        setNotificationUris(cr, notifyUris, cr.getUserId());
+        setNotificationUris(cr, notifyUris, cr.getUserId(), true);
     }
 
-    /** @hide - set the notification uri but with an observer for a particular user's view */
-    public void setNotificationUris(ContentResolver cr, List<Uri> notifyUris, int userHandle) {
+    /**
+     * Set the notification uri but with an observer for a particular user's view. Also allows
+     * disabling the use of a self observer, which is sensible if either
+     * a) the cursor's owner calls {@link #onChange(boolean)} whenever the content changes, or
+     * b) the cursor is known not to have any content observers.
+     * @hide
+     */
+    public void setNotificationUris(ContentResolver cr, List<Uri> notifyUris, int userHandle,
+            boolean registerSelfObserver) {
         synchronized (mSelfObserverLock) {
             mNotifyUris = notifyUris;
             mNotifyUri = mNotifyUris.get(0);
             mContentResolver = cr;
             if (mSelfObserver != null) {
                 mContentResolver.unregisterContentObserver(mSelfObserver);
+                mSelfObserverRegistered = false;
             }
-            mSelfObserver = new SelfContentObserver(this);
-            final int size = mNotifyUris.size();
-            for (int i = 0; i < size; ++i) {
-                final Uri notifyUri = mNotifyUris.get(i);
-                mContentResolver.registerContentObserver(
-                        notifyUri, true, mSelfObserver, userHandle);
+            if (registerSelfObserver) {
+                mSelfObserver = new SelfContentObserver(this);
+                final int size = mNotifyUris.size();
+                for (int i = 0; i < size; ++i) {
+                    final Uri notifyUri = mNotifyUris.get(i);
+                    mContentResolver.registerContentObserver(
+                            notifyUri, true, mSelfObserver, userHandle);
+                }
+                mSelfObserverRegistered = true;
             }
-            mSelfObserverRegistered = true;
         }
     }
 
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 83e1980..3cdebac 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -26,12 +26,14 @@
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
+import android.util.Log;
 
 import com.android.internal.util.Preconditions;
 
 import libcore.io.IoUtils;
 
-import java.io.FileDescriptor;
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.concurrent.Executor;
@@ -45,6 +47,9 @@
 @TestApi
 @SystemService(Context.BUGREPORT_SERVICE)
 public final class BugreportManager {
+
+    private static final String TAG = "BugreportManager";
+
     private final Context mContext;
     private final IDumpstate mBinder;
 
@@ -149,16 +154,22 @@
             Preconditions.checkNotNull(executor);
             Preconditions.checkNotNull(callback);
 
+            if (screenshotFd == null) {
+                // Binder needs a valid File Descriptor to be passed
+                screenshotFd = ParcelFileDescriptor.open(new File("/dev/null"),
+                        ParcelFileDescriptor.MODE_READ_ONLY);
+            }
             DumpstateListener dsListener = new DumpstateListener(executor, callback);
             // Note: mBinder can get callingUid from the binder transaction.
             mBinder.startBugreport(-1 /* callingUid */,
                     mContext.getOpPackageName(),
                     bugreportFd.getFileDescriptor(),
-                    (screenshotFd != null
-                            ? screenshotFd.getFileDescriptor() : new FileDescriptor()),
+                    screenshotFd.getFileDescriptor(),
                     params.getMode(), dsListener);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
+        } catch (FileNotFoundException e) {
+            Log.wtf(TAG, "Not able to find /dev/null file: ", e);
         } finally {
             // We can close the file descriptors here because binder would have duped them.
             IoUtils.closeQuietly(bugreportFd);
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index d415387..83abf1a 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -173,6 +173,6 @@
     }
 
     private InputMethodManager getImm() {
-        return mController.getViewRoot().mDisplayContext.getSystemService(InputMethodManager.class);
+        return mController.getViewRoot().mContext.getSystemService(InputMethodManager.class);
     }
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b813bc3..4463e13 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -283,13 +283,7 @@
     @GuardedBy("mWindowCallbacks")
     final ArrayList<WindowCallbacks> mWindowCallbacks = new ArrayList<>();
     @UnsupportedAppUsage
-    final Context mContext;
-    /**
-     * TODO(b/116349163): Check if we can merge this into {@link #mContext}.
-     * @hide
-     */
-    @NonNull
-    public Context mDisplayContext;
+    public final Context mContext;
 
     @UnsupportedAppUsage
     final IWindowSession mWindowSession;
@@ -595,7 +589,6 @@
 
     public ViewRootImpl(Context context, Display display) {
         mContext = context;
-        mDisplayContext = context.createDisplayContext(display);
         mWindowSession = WindowManagerGlobal.getWindowSession();
         mDisplay = display;
         mBasePackageName = context.getBasePackageName();
@@ -1379,7 +1372,7 @@
         } else {
             mDisplay = preferredDisplay;
         }
-        mDisplayContext = mContext.createDisplayContext(mDisplay);
+        mContext.updateDisplay(mDisplay.getDisplayId());
     }
 
     void pokeDrawLockIfNeeded() {
@@ -2725,7 +2718,7 @@
                     .mayUseInputMethod(mWindowAttributes.flags);
             if (imTarget != mLastWasImTarget) {
                 mLastWasImTarget = imTarget;
-                InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
+                InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
                 if (imm != null && imTarget) {
                     imm.onPreWindowFocus(mView, hasWindowFocus);
                     imm.onPostWindowFocus(mView, mView.findFocus(),
@@ -2859,7 +2852,7 @@
             mLastWasImTarget = WindowManager.LayoutParams
                     .mayUseInputMethod(mWindowAttributes.flags);
 
-            InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
+            InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
             if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
                 imm.onPreWindowFocus(mView, hasWindowFocus);
             }
@@ -4564,8 +4557,7 @@
                     enqueueInputEvent(event, null, 0, true);
                 } break;
                 case MSG_CHECK_FOCUS: {
-                    InputMethodManager imm =
-                            mDisplayContext.getSystemService(InputMethodManager.class);
+                    InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
                     if (imm != null) {
                         imm.checkFocus();
                     }
@@ -5110,7 +5102,7 @@
         @Override
         protected int onProcess(QueuedInputEvent q) {
             if (mLastWasImTarget && !isInLocalFocusMode()) {
-                InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
+                InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
                 if (imm != null) {
                     final InputEvent event = q.mEvent;
                     if (DEBUG_IMF) Log.v(mTag, "Sending input event to IME: " + event);
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java
index ee5b3ec..21ead4c 100644
--- a/core/java/android/view/inputmethod/CursorAnchorInfo.java
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java
@@ -17,6 +17,7 @@
 package android.view.inputmethod;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.graphics.Matrix;
 import android.graphics.RectF;
 import android.os.Parcel;
@@ -388,7 +389,7 @@
                             "required when positional parameters are specified.");
                 }
             }
-            return new CursorAnchorInfo(this);
+            return CursorAnchorInfo.create(this);
         }
 
         /**
@@ -412,30 +413,90 @@
         }
     }
 
-    private CursorAnchorInfo(final Builder builder) {
-        mSelectionStart = builder.mSelectionStart;
-        mSelectionEnd = builder.mSelectionEnd;
-        mComposingTextStart = builder.mComposingTextStart;
-        mComposingText = builder.mComposingText;
-        mInsertionMarkerFlags = builder.mInsertionMarkerFlags;
-        mInsertionMarkerHorizontal = builder.mInsertionMarkerHorizontal;
-        mInsertionMarkerTop = builder.mInsertionMarkerTop;
-        mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline;
-        mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
-        mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null ?
-                builder.mCharacterBoundsArrayBuilder.build() : null;
-        mMatrixValues = new float[9];
+    private static CursorAnchorInfo create(Builder builder) {
+        final SparseRectFArray characterBoundsArray =
+                builder.mCharacterBoundsArrayBuilder != null
+                        ? builder.mCharacterBoundsArrayBuilder.build()
+                        : null;
+        final float[] matrixValues = new float[9];
         if (builder.mMatrixInitialized) {
-            System.arraycopy(builder.mMatrixValues, 0, mMatrixValues, 0, 9);
+            System.arraycopy(builder.mMatrixValues, 0, matrixValues, 0, 9);
         } else {
-            Matrix.IDENTITY_MATRIX.getValues(mMatrixValues);
+            Matrix.IDENTITY_MATRIX.getValues(matrixValues);
         }
 
+        return new CursorAnchorInfo(builder.mSelectionStart, builder.mSelectionEnd,
+                builder.mComposingTextStart, builder.mComposingText, builder.mInsertionMarkerFlags,
+                builder.mInsertionMarkerHorizontal, builder.mInsertionMarkerTop,
+                builder.mInsertionMarkerBaseline, builder.mInsertionMarkerBottom,
+                characterBoundsArray, matrixValues);
+    }
+
+    private CursorAnchorInfo(int selectionStart, int selectionEnd, int composingTextStart,
+            @Nullable CharSequence composingText, int insertionMarkerFlags,
+            float insertionMarkerHorizontal, float insertionMarkerTop,
+            float insertionMarkerBaseline, float insertionMarkerBottom,
+            @Nullable  SparseRectFArray characterBoundsArray, @NonNull float[] matrixValues) {
+        mSelectionStart = selectionStart;
+        mSelectionEnd = selectionEnd;
+        mComposingTextStart = composingTextStart;
+        mComposingText = composingText;
+        mInsertionMarkerFlags = insertionMarkerFlags;
+        mInsertionMarkerHorizontal = insertionMarkerHorizontal;
+        mInsertionMarkerTop = insertionMarkerTop;
+        mInsertionMarkerBaseline = insertionMarkerBaseline;
+        mInsertionMarkerBottom = insertionMarkerBottom;
+        mCharacterBoundsArray = characterBoundsArray;
+        mMatrixValues = matrixValues;
+
         // To keep hash function simple, we only use some complex objects for hash.
-        int hash = Objects.hashCode(mComposingText);
-        hash *= 31;
-        hash += Arrays.hashCode(mMatrixValues);
-        mHashCode = hash;
+        int hashCode = Objects.hashCode(mComposingText);
+        hashCode *= 31;
+        hashCode += Arrays.hashCode(matrixValues);
+        mHashCode = hashCode;
+    }
+
+    /**
+     * Creates a new instance of {@link CursorAnchorInfo} by applying {@code parentMatrix} to
+     * the coordinate transformation matrix.
+     *
+     * @param original {@link CursorAnchorInfo} to be cloned from.
+     * @param parentMatrix {@link Matrix} to be applied to {@code original.getMatrix()}
+     * @return A new instance of {@link CursorAnchorInfo} whose {@link CursorAnchorInfo#getMatrix()}
+     *         returns {@code parentMatrix * original.getMatrix()}.
+     * @hide
+     */
+    public static CursorAnchorInfo createForAdditionalParentMatrix(CursorAnchorInfo original,
+            @NonNull Matrix parentMatrix) {
+        return new CursorAnchorInfo(original.mSelectionStart, original.mSelectionEnd,
+                original.mComposingTextStart, original.mComposingText,
+                original.mInsertionMarkerFlags, original.mInsertionMarkerHorizontal,
+                original.mInsertionMarkerTop, original.mInsertionMarkerBaseline,
+                original.mInsertionMarkerBottom, original.mCharacterBoundsArray,
+                computeMatrixValues(parentMatrix, original));
+    }
+
+    /**
+     * Returns a float array that represents {@link Matrix} elements for
+     * {@code parentMatrix * info.getMatrix()}.
+     *
+     * @param parentMatrix {@link Matrix} to be multiplied.
+     * @param info {@link CursorAnchorInfo} to provide {@link Matrix} to be multiplied.
+     * @return {@code parentMatrix * info.getMatrix()}.
+     */
+    private static float[] computeMatrixValues(@NonNull Matrix parentMatrix,
+            @NonNull CursorAnchorInfo info) {
+        if (parentMatrix.isIdentity()) {
+            return info.mMatrixValues;
+        }
+
+        final Matrix newMatrix = new Matrix();
+        newMatrix.setValues(info.mMatrixValues);
+        newMatrix.postConcat(parentMatrix);
+
+        final float[] matrixValues = new float[9];
+        newMatrix.getValues(matrixValues);
+        return matrixValues;
     }
 
     /**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index fd73856..c7b1cda 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -510,7 +510,7 @@
             return null;
         }
         final InputMethodManager fallbackImm =
-                viewRootImpl.mDisplayContext.getSystemService(InputMethodManager.class);
+                viewRootImpl.mContext.getSystemService(InputMethodManager.class);
         if (fallbackImm == null) {
             Log.e(TAG, "b/117267690: Failed to get non-null fallback IMM. view=" + view);
             return null;
@@ -2887,6 +2887,16 @@
         }
     }
 
+    /**
+     * <p>This is used for CTS test only. Do not use this method outside of CTS package.<p/>
+     * @return the ID of this display which this {@link InputMethodManager} resides
+     * @hide
+     */
+    @TestApi
+    public int getDisplayId() {
+        return mDisplayId;
+    }
+
     void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
         final Printer p = new PrintWriterPrinter(fout);
         p.println("Input method client state for " + this + ":");
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 2349c31..b605eaf 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -177,7 +177,7 @@
      */
     private static final int NO_DIRECT_SHARE_ANIM_IN_MILLIS = 200;
 
-    private static final float DIRECT_SHARE_EXPANSION_RATE = 0.7f;
+    private static final float DIRECT_SHARE_EXPANSION_RATE = 0.78f;
 
     // TODO(b/121287224): Re-evaluate this limit
     private static final int SHARE_TARGET_QUERY_PACKAGE_LIMIT = 20;
@@ -2037,21 +2037,29 @@
                     return;
                 }
 
-                int lastHeight = 0;
+                int directShareHeight = 0;
                 rowsToShow = Math.min(4, rowsToShow);
                 for (int i = 0; i < Math.min(rowsToShow, mAdapterView.getChildCount()); i++) {
-                    lastHeight = mAdapterView.getChildAt(i).getHeight();
-                    offset += lastHeight;
+                    View child = mAdapterView.getChildAt(i);
+                    int height = child.getHeight();
+                    offset += height;
+
+                    if (child.getTag() != null
+                            && (child.getTag() instanceof DirectShareViewHolder)) {
+                        directShareHeight = height;
+                    }
                 }
 
                 boolean isPortrait = getResources().getConfiguration().orientation
                                          == Configuration.ORIENTATION_PORTRAIT;
-                if (lastHeight != 0 && isSendAction(getTargetIntent()) && isPortrait) {
+                if (directShareHeight != 0 && isSendAction(getTargetIntent()) && isPortrait) {
                     // make sure to leave room for direct share 4->8 expansion
-                    int expansionArea =
-                            (int) (mResolverDrawerLayout.getAlwaysShowHeight()
-                                    / DIRECT_SHARE_EXPANSION_RATE);
-                    offset = Math.min(offset, bottom - top - lastHeight - expansionArea);
+                    int requiredExpansionHeight =
+                            (int) (directShareHeight / DIRECT_SHARE_EXPANSION_RATE);
+                    int minHeight = bottom - top - mResolverDrawerLayout.getAlwaysShowHeight()
+                                        - requiredExpansionHeight;
+
+                    offset = Math.min(offset, minHeight);
                 }
 
                 mResolverDrawerLayout.setCollapsibleHeightReserved(Math.min(offset, bottom - top));
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index 9e8bd64..cc2caca 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -60,9 +60,11 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * A helper class for {@link android.provider.DocumentsProvider} to perform file operations on local
@@ -613,28 +615,28 @@
         return projection == null ? mDefaultProjection : projection;
     }
 
-    private void startObserving(File file, Uri notifyUri) {
+    private void startObserving(File file, Uri notifyUri, DirectoryCursor cursor) {
         synchronized (mObservers) {
             DirectoryObserver observer = mObservers.get(file);
             if (observer == null) {
-                observer = new DirectoryObserver(
-                        file, getContext().getContentResolver(), notifyUri);
+                observer =
+                        new DirectoryObserver(file, getContext().getContentResolver(), notifyUri);
                 observer.startWatching();
                 mObservers.put(file, observer);
             }
-            observer.mRefCount++;
+            observer.mCursors.add(cursor);
 
             if (LOG_INOTIFY) Log.d(TAG, "after start: " + observer);
         }
     }
 
-    private void stopObserving(File file) {
+    private void stopObserving(File file, DirectoryCursor cursor) {
         synchronized (mObservers) {
             DirectoryObserver observer = mObservers.get(file);
             if (observer == null) return;
 
-            observer.mRefCount--;
-            if (observer.mRefCount == 0) {
+            observer.mCursors.remove(cursor);
+            if (observer.mCursors.size() == 0) {
                 mObservers.remove(file);
                 observer.stopWatching();
             }
@@ -650,27 +652,31 @@
         private final File mFile;
         private final ContentResolver mResolver;
         private final Uri mNotifyUri;
+        private final CopyOnWriteArrayList<DirectoryCursor> mCursors;
 
-        private int mRefCount = 0;
-
-        public DirectoryObserver(File file, ContentResolver resolver, Uri notifyUri) {
+        DirectoryObserver(File file, ContentResolver resolver, Uri notifyUri) {
             super(file.getAbsolutePath(), NOTIFY_EVENTS);
             mFile = file;
             mResolver = resolver;
             mNotifyUri = notifyUri;
+            mCursors = new CopyOnWriteArrayList<>();
         }
 
         @Override
         public void onEvent(int event, String path) {
             if ((event & NOTIFY_EVENTS) != 0) {
                 if (LOG_INOTIFY) Log.d(TAG, "onEvent() " + event + " at " + path);
+                for (DirectoryCursor cursor : mCursors) {
+                    cursor.notifyChanged();
+                }
                 mResolver.notifyChange(mNotifyUri, null, false);
             }
         }
 
         @Override
         public String toString() {
-            return "DirectoryObserver{file=" + mFile.getAbsolutePath() + ", ref=" + mRefCount + "}";
+            String filePath = mFile.getAbsolutePath();
+            return "DirectoryObserver{file=" + filePath + ", ref=" + mCursors.size() + "}";
         }
     }
 
@@ -681,16 +687,22 @@
             super(columnNames);
 
             final Uri notifyUri = buildNotificationUri(docId);
-            setNotificationUri(getContext().getContentResolver(), notifyUri);
+            boolean registerSelfObserver = false; // Our FileObserver sees all relevant changes.
+            setNotificationUris(getContext().getContentResolver(), Arrays.asList(notifyUri),
+                    getContext().getContentResolver().getUserId(), registerSelfObserver);
 
             mFile = file;
-            startObserving(mFile, notifyUri);
+            startObserving(mFile, notifyUri, this);
+        }
+
+        public void notifyChanged() {
+            onChange(false);
         }
 
         @Override
         public void close() {
             super.close();
-            stopObserving(mFile);
+            stopObserving(mFile, this);
         }
     }
 }
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index dbd2191..e6ae226 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -159,6 +159,9 @@
     optional int32 surface_size = 14 [deprecated=true];
     optional string focused_app = 15;
     optional AppTransitionProto app_transition = 16;
+    repeated IdentifierProto opening_apps = 17;
+    repeated IdentifierProto closing_apps = 18;
+    repeated IdentifierProto changing_apps = 19;
 }
 
 /* represents DisplayFrames */
diff --git a/core/res/res/layout/chooser_grid_preview_text.xml b/core/res/res/layout/chooser_grid_preview_text.xml
index 96a642c..9c725b9 100644
--- a/core/res/res/layout/chooser_grid_preview_text.xml
+++ b/core/res/res/layout/chooser_grid_preview_text.xml
@@ -23,7 +23,6 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
-    android:paddingBottom="@dimen/chooser_view_spacing"
     android:background="?android:attr/colorBackgroundFloating">
 
   <RelativeLayout
@@ -91,6 +90,7 @@
       android:orientation="horizontal"
       android:layout_marginLeft="@dimen/chooser_edge_margin_normal"
       android:layout_marginRight="@dimen/chooser_edge_margin_normal"
+      android:layout_marginBottom="@dimen/chooser_view_spacing"
       android:minHeight="80dp"
       android:background="@drawable/chooser_content_preview_rounded"
       android:id="@+id/content_preview_title_layout">
diff --git a/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java
index ace6611..833530d 100644
--- a/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java
@@ -16,19 +16,9 @@
 
 package android.view.inputmethod;
 
-import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
-import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
-import static android.view.inputmethod.CursorAnchorInfo.FLAG_IS_RTL;
-
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
 
 import android.graphics.Matrix;
-import android.graphics.RectF;
-import android.os.Parcel;
-import android.text.TextUtils;
 import android.view.inputmethod.CursorAnchorInfo.Builder;
 
 import androidx.test.filters.SmallTest;
@@ -37,437 +27,38 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.Objects;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class CursorAnchorInfoTest {
-    private static final float EPSILON = 0.0000001f;
-
-    private static final RectF[] MANY_BOUNDS = new RectF[] {
-            new RectF(101.0f, 201.0f, 301.0f, 401.0f),
-            new RectF(102.0f, 202.0f, 302.0f, 402.0f),
-            new RectF(103.0f, 203.0f, 303.0f, 403.0f),
-            new RectF(104.0f, 204.0f, 304.0f, 404.0f),
-            new RectF(105.0f, 205.0f, 305.0f, 405.0f),
-            new RectF(106.0f, 206.0f, 306.0f, 406.0f),
-            new RectF(107.0f, 207.0f, 307.0f, 407.0f),
-            new RectF(108.0f, 208.0f, 308.0f, 408.0f),
-            new RectF(109.0f, 209.0f, 309.0f, 409.0f),
-            new RectF(110.0f, 210.0f, 310.0f, 410.0f),
-            new RectF(111.0f, 211.0f, 311.0f, 411.0f),
-            new RectF(112.0f, 212.0f, 312.0f, 412.0f),
-            new RectF(113.0f, 213.0f, 313.0f, 413.0f),
-            new RectF(114.0f, 214.0f, 314.0f, 414.0f),
-            new RectF(115.0f, 215.0f, 315.0f, 415.0f),
-            new RectF(116.0f, 216.0f, 316.0f, 416.0f),
-            new RectF(117.0f, 217.0f, 317.0f, 417.0f),
-            new RectF(118.0f, 218.0f, 318.0f, 418.0f),
-            new RectF(119.0f, 219.0f, 319.0f, 419.0f),
-    };
-    private static final int[] MANY_FLAGS_ARRAY = new int[] {
-        FLAG_HAS_INVISIBLE_REGION,
-        FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION,
-        FLAG_HAS_VISIBLE_REGION,
-        FLAG_HAS_VISIBLE_REGION,
-        FLAG_HAS_VISIBLE_REGION,
-        FLAG_HAS_VISIBLE_REGION,
-        FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
-        FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
-        FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL,
-        FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
-        FLAG_HAS_VISIBLE_REGION,
-        FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
-        FLAG_HAS_VISIBLE_REGION,
-        FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
-        FLAG_HAS_VISIBLE_REGION,
-        FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
-        FLAG_HAS_VISIBLE_REGION,
-        FLAG_HAS_INVISIBLE_REGION,
-        FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL,
-    };
-
     @Test
-    public void testBuilder() throws Exception {
-        final int SELECTION_START = 30;
-        final int SELECTION_END = 40;
-        final int COMPOSING_TEXT_START = 32;
-        final String COMPOSING_TEXT = "test";
-        final int INSERTION_MARKER_FLAGS =
-                FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL;
-        final float INSERTION_MARKER_HORIZONTAL = 10.5f;
-        final float INSERTION_MARKER_TOP = 100.1f;
-        final float INSERTION_MARKER_BASELINE = 110.4f;
-        final float INSERTION_MARKER_BOTOM = 111.0f;
-
-        Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX);
-        TRANSFORM_MATRIX.setScale(10.0f, 20.0f);
-
+    public void testCreateForAdditionalParentMatrix() {
+        final Matrix originalMatrix = new Matrix();
+        originalMatrix.setTranslate(10.0f, 20.0f);
         final Builder builder = new Builder();
-        builder.setSelectionRange(SELECTION_START, SELECTION_END)
-                .setComposingText(COMPOSING_TEXT_START, COMPOSING_TEXT)
-                .setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
-                        INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS)
-                .setMatrix(TRANSFORM_MATRIX);
-        for (int i = 0; i < MANY_BOUNDS.length; i++) {
-            final RectF bounds = MANY_BOUNDS[i];
-            final int flags = MANY_FLAGS_ARRAY[i];
-            builder.addCharacterBounds(i, bounds.left, bounds.top, bounds.right, bounds.bottom,
-                    flags);
-        }
+        builder.setMatrix(originalMatrix);
 
-        final CursorAnchorInfo info = builder.build();
-        assertEquals(SELECTION_START, info.getSelectionStart());
-        assertEquals(SELECTION_END, info.getSelectionEnd());
-        assertEquals(COMPOSING_TEXT_START, info.getComposingTextStart());
-        assertTrue(TextUtils.equals(COMPOSING_TEXT, info.getComposingText()));
-        assertEquals(INSERTION_MARKER_FLAGS, info.getInsertionMarkerFlags());
-        assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal(), EPSILON);
-        assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop(), EPSILON);
-        assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline(), EPSILON);
-        assertEquals(INSERTION_MARKER_BOTOM, info.getInsertionMarkerBottom(), EPSILON);
-        assertEquals(TRANSFORM_MATRIX, info.getMatrix());
-        for (int i = 0; i < MANY_BOUNDS.length; i++) {
-            final RectF expectedBounds = MANY_BOUNDS[i];
-            assertEquals(expectedBounds, info.getCharacterBounds(i));
-        }
-        assertNull(info.getCharacterBounds(-1));
-        assertNull(info.getCharacterBounds(MANY_BOUNDS.length + 1));
-        for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
-            final int expectedFlags = MANY_FLAGS_ARRAY[i];
-            assertEquals(expectedFlags, info.getCharacterBoundsFlags(i));
-        }
-        assertEquals(0, info.getCharacterBoundsFlags(-1));
-        assertEquals(0, info.getCharacterBoundsFlags(MANY_BOUNDS.length + 1));
+        final CursorAnchorInfo originalInstance = builder.build();
 
-        // Make sure that the builder can reproduce the same object.
-        final CursorAnchorInfo info2 = builder.build();
-        assertEquals(SELECTION_START, info2.getSelectionStart());
-        assertEquals(SELECTION_END, info2.getSelectionEnd());
-        assertEquals(COMPOSING_TEXT_START, info2.getComposingTextStart());
-        assertTrue(TextUtils.equals(COMPOSING_TEXT, info2.getComposingText()));
-        assertEquals(INSERTION_MARKER_FLAGS, info2.getInsertionMarkerFlags());
-        assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal(), EPSILON);
-        assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop(), EPSILON);
-        assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline(), EPSILON);
-        assertEquals(INSERTION_MARKER_BOTOM, info2.getInsertionMarkerBottom(), EPSILON);
-        assertEquals(TRANSFORM_MATRIX, info2.getMatrix());
-        for (int i = 0; i < MANY_BOUNDS.length; i++) {
-            final RectF expectedBounds = MANY_BOUNDS[i];
-            assertEquals(expectedBounds, info2.getCharacterBounds(i));
-        }
-        assertNull(info2.getCharacterBounds(-1));
-        assertNull(info2.getCharacterBounds(MANY_BOUNDS.length + 1));
-        for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
-            final int expectedFlags = MANY_FLAGS_ARRAY[i];
-            assertEquals(expectedFlags, info2.getCharacterBoundsFlags(i));
-        }
-        assertEquals(0, info2.getCharacterBoundsFlags(-1));
-        assertEquals(0, info2.getCharacterBoundsFlags(MANY_BOUNDS.length + 1));
-        assertEquals(info, info2);
-        assertEquals(info.hashCode(), info2.hashCode());
+        assertEquals(originalMatrix, originalInstance.getMatrix());
 
-        // Make sure that object can be marshaled via {@link Parsel}.
-        final CursorAnchorInfo info3 = cloneViaParcel(info2);
-        assertEquals(SELECTION_START, info3.getSelectionStart());
-        assertEquals(SELECTION_END, info3.getSelectionEnd());
-        assertEquals(COMPOSING_TEXT_START, info3.getComposingTextStart());
-        assertTrue(TextUtils.equals(COMPOSING_TEXT, info3.getComposingText()));
-        assertEquals(INSERTION_MARKER_FLAGS, info3.getInsertionMarkerFlags());
-        assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal(), EPSILON);
-        assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop(), EPSILON);
-        assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline(), EPSILON);
-        assertEquals(INSERTION_MARKER_BOTOM, info3.getInsertionMarkerBottom(), EPSILON);
-        assertEquals(TRANSFORM_MATRIX, info3.getMatrix());
-        for (int i = 0; i < MANY_BOUNDS.length; i++) {
-            final RectF expectedBounds = MANY_BOUNDS[i];
-            assertEquals(expectedBounds, info3.getCharacterBounds(i));
-        }
-        assertNull(info3.getCharacterBounds(-1));
-        assertNull(info3.getCharacterBounds(MANY_BOUNDS.length + 1));
-        for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
-            final int expectedFlags = MANY_FLAGS_ARRAY[i];
-            assertEquals(expectedFlags, info3.getCharacterBoundsFlags(i));
-        }
-        assertEquals(0, info3.getCharacterBoundsFlags(-1));
-        assertEquals(0, info3.getCharacterBoundsFlags(MANY_BOUNDS.length + 1));
-        assertEquals(info.hashCode(), info3.hashCode());
+        final Matrix additionalParentMatrix = new Matrix();
+        additionalParentMatrix.setTranslate(1.0f, 2.0f);
+
+        final Matrix newMatrix = new Matrix(originalMatrix);
+        newMatrix.postConcat(additionalParentMatrix);
 
         builder.reset();
-        final CursorAnchorInfo uninitializedInfo = builder.build();
-        assertEquals(-1, uninitializedInfo.getSelectionStart());
-        assertEquals(-1, uninitializedInfo.getSelectionEnd());
-        assertEquals(-1, uninitializedInfo.getComposingTextStart());
-        assertNull(uninitializedInfo.getComposingText());
-        assertEquals(0, uninitializedInfo.getInsertionMarkerFlags());
-        assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal(), EPSILON);
-        assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop(), EPSILON);
-        assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline(), EPSILON);
-        assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBottom(), EPSILON);
-        assertEquals(Matrix.IDENTITY_MATRIX, uninitializedInfo.getMatrix());
-    }
+        builder.setMatrix(newMatrix);
+        // An instance created by the standard Builder class.
+        final CursorAnchorInfo newInstanceByBuilder = builder.build();
 
-    private static void assertNotEquals(final CursorAnchorInfo reference,
-            final CursorAnchorInfo actual) {
-        assertFalse(Objects.equals(reference, actual));
-    }
+        // An instance created by an @hide method.
+        final CursorAnchorInfo newInstanceByMethod =
+                CursorAnchorInfo.createForAdditionalParentMatrix(
+                        originalInstance, additionalParentMatrix);
 
-    @Test
-    public void testEquality() throws Exception {
-        final Matrix MATRIX1 = new Matrix();
-        MATRIX1.setTranslate(10.0f, 20.0f);
-        final Matrix MATRIX2 = new Matrix();
-        MATRIX2.setTranslate(110.0f, 120.0f);
-        final Matrix NAN_MATRIX = new Matrix();
-        NAN_MATRIX.setValues(new float[]{
-                Float.NaN, Float.NaN, Float.NaN,
-                Float.NaN, Float.NaN, Float.NaN,
-                Float.NaN, Float.NaN, Float.NaN});
-        final int SELECTION_START1 = 2;
-        final int SELECTION_END1 = 7;
-        final String COMPOSING_TEXT1 = "0123456789";
-        final int COMPOSING_TEXT_START1 = 0;
-        final int INSERTION_MARKER_FLAGS1 = FLAG_HAS_VISIBLE_REGION;
-        final float INSERTION_MARKER_HORIZONTAL1 = 10.5f;
-        final float INSERTION_MARKER_TOP1 = 100.1f;
-        final float INSERTION_MARKER_BASELINE1 = 110.4f;
-        final float INSERTION_MARKER_BOTOM1 = 111.0f;
-        final int SELECTION_START2 = 4;
-        final int SELECTION_END2 = 8;
-        final String COMPOSING_TEXT2 = "9876543210";
-        final int COMPOSING_TEXT_START2 = 3;
-        final int INSERTION_MARKER_FLAGS2 =
-                FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL;
-        final float INSERTION_MARKER_HORIZONTAL2 = 14.5f;
-        final float INSERTION_MARKER_TOP2 = 200.1f;
-        final float INSERTION_MARKER_BASELINE2 = 210.4f;
-        final float INSERTION_MARKER_BOTOM2 = 211.0f;
-
-        // Default instance should be equal.
-        assertEquals(new Builder().build(), new Builder().build());
-
-        assertEquals(
-                new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(),
-                new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build());
-        assertNotEquals(
-                new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(),
-                new Builder().setSelectionRange(SELECTION_START1, SELECTION_END2).build());
-        assertNotEquals(
-                new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(),
-                new Builder().setSelectionRange(SELECTION_START2, SELECTION_END1).build());
-        assertNotEquals(
-                new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(),
-                new Builder().setSelectionRange(SELECTION_START2, SELECTION_END2).build());
-        assertEquals(
-                new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(),
-                new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build());
-        assertNotEquals(
-                new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(),
-                new Builder().setComposingText(COMPOSING_TEXT_START2, COMPOSING_TEXT1).build());
-        assertNotEquals(
-                new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(),
-                new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT2).build());
-        assertNotEquals(
-                new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(),
-                new Builder().setComposingText(COMPOSING_TEXT_START2, COMPOSING_TEXT2).build());
-
-        // For insertion marker locations, {@link Float#NaN} is treated as if it was a number.
-        assertEquals(
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        Float.NaN, Float.NaN, Float.NaN, Float.NaN,
-                        INSERTION_MARKER_FLAGS1).build(),
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        Float.NaN, Float.NaN, Float.NaN, Float.NaN,
-                        INSERTION_MARKER_FLAGS1).build());
-
-        // Check Matrix.
-        assertEquals(
-                new Builder().setMatrix(MATRIX1).build(),
-                new Builder().setMatrix(MATRIX1).build());
-        assertNotEquals(
-                new Builder().setMatrix(MATRIX1).build(),
-                new Builder().setMatrix(MATRIX2).build());
-        assertNotEquals(
-                new Builder().setMatrix(MATRIX1).build(),
-                new Builder().setMatrix(NAN_MATRIX).build());
-        // Unlike insertion marker locations, {@link Float#NaN} in the matrix is treated as just a
-        // NaN as usual (NaN == NaN -> false).
-        assertNotEquals(
-                new Builder().setMatrix(NAN_MATRIX).build(),
-                new Builder().setMatrix(NAN_MATRIX).build());
-
-        assertEquals(
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build(),
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build());
-        assertNotEquals(
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        Float.NaN, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build(),
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build());
-        assertNotEquals(
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build(),
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build());
-        assertNotEquals(
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build(),
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP2,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build());
-        assertNotEquals(
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build(),
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE2, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build());
-        assertNotEquals(
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build(),
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build());
-        assertNotEquals(
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build(),
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM2,
-                        INSERTION_MARKER_FLAGS1).build());
-        assertNotEquals(
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS1).build(),
-                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
-                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
-                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
-                        INSERTION_MARKER_FLAGS2).build());
-    }
-
-    @Test
-    public void testMatrixIsCopied() throws Exception {
-        final Matrix MATRIX1 = new Matrix();
-        MATRIX1.setTranslate(10.0f, 20.0f);
-        final Matrix MATRIX2 = new Matrix();
-        MATRIX2.setTranslate(110.0f, 120.0f);
-        final Matrix MATRIX3 = new Matrix();
-        MATRIX3.setTranslate(210.0f, 220.0f);
-        final Matrix matrix = new Matrix();
-        final Builder builder = new Builder();
-
-        matrix.set(MATRIX1);
-        builder.setMatrix(matrix);
-        matrix.postRotate(90.0f);
-
-        final CursorAnchorInfo firstInstance = builder.build();
-        assertEquals(MATRIX1, firstInstance.getMatrix());
-        matrix.set(MATRIX2);
-        builder.setMatrix(matrix);
-        final CursorAnchorInfo secondInstance = builder.build();
-        assertEquals(MATRIX1, firstInstance.getMatrix());
-        assertEquals(MATRIX2, secondInstance.getMatrix());
-
-        matrix.set(MATRIX3);
-        assertEquals(MATRIX1, firstInstance.getMatrix());
-        assertEquals(MATRIX2, secondInstance.getMatrix());
-    }
-
-    @Test
-    public void testMatrixIsRequired() throws Exception {
-        final int SELECTION_START = 30;
-        final int SELECTION_END = 40;
-        final int COMPOSING_TEXT_START = 32;
-        final String COMPOSING_TEXT = "test";
-        final int INSERTION_MARKER_FLAGS = FLAG_HAS_VISIBLE_REGION;
-        final float INSERTION_MARKER_HORIZONTAL = 10.5f;
-        final float INSERTION_MARKER_TOP = 100.1f;
-        final float INSERTION_MARKER_BASELINE = 110.4f;
-        final float INSERTION_MARKER_BOTOM = 111.0f;
-        Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX);
-        TRANSFORM_MATRIX.setScale(10.0f, 20.0f);
-
-        final Builder builder = new Builder();
-        // Check twice to make sure if Builder#reset() works as expected.
-        for (int repeatCount = 0; repeatCount < 2; ++repeatCount) {
-            builder.setSelectionRange(SELECTION_START, SELECTION_END)
-                    .setComposingText(COMPOSING_TEXT_START, COMPOSING_TEXT);
-            try {
-                // Should succeed as coordinate transformation matrix is not required if no
-                // positional information is specified.
-                builder.build();
-            } catch (IllegalArgumentException ex) {
-                assertTrue(false);
-            }
-
-            builder.setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
-                    INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS);
-            try {
-                // Coordinate transformation matrix is required if no positional information is
-                // specified.
-                builder.build();
-                assertTrue(false);
-            } catch (IllegalArgumentException ex) {
-            }
-
-            builder.setMatrix(TRANSFORM_MATRIX);
-            try {
-                // Should succeed as coordinate transformation matrix is required.
-                builder.build();
-            } catch (IllegalArgumentException ex) {
-                assertTrue(false);
-            }
-
-            builder.reset();
-        }
-    }
-
-    @Test
-    public void testBuilderAddCharacterBounds() throws Exception {
-        // A negative index should be rejected.
-        try {
-            new Builder().addCharacterBounds(-1, 0.0f, 0.0f, 0.0f, 0.0f, FLAG_HAS_VISIBLE_REGION);
-            assertTrue(false);
-        } catch (IllegalArgumentException ex) {
-        }
-    }
-
-    private static CursorAnchorInfo cloneViaParcel(final CursorAnchorInfo src) {
-        Parcel parcel = null;
-        try {
-            parcel = Parcel.obtain();
-            src.writeToParcel(parcel, 0);
-            parcel.setDataPosition(0);
-            return new CursorAnchorInfo(parcel);
-        } finally {
-            if (parcel != null) {
-                parcel.recycle();
-            }
-        }
+        assertEquals(newMatrix, newInstanceByBuilder.getMatrix());
+        assertEquals(newMatrix, newInstanceByMethod.getMatrix());
+        assertEquals(newInstanceByBuilder.hashCode(), newInstanceByMethod.hashCode());
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index ff34578..1d351a5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -50,6 +50,8 @@
 
     // See mConnectAttempted
     private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000;
+    // Some Hearing Aids (especially the 2nd device) needs more time to do service discovery
+    private static final long MAX_HEARING_AIDS_DELAY_FOR_AUTO_CONNECT = 15000;
     private static final long MAX_HOGP_DELAY_FOR_AUTO_CONNECT = 30000;
 
     private final Context mContext;
@@ -223,7 +225,7 @@
                 // various profiles
                 // If UUIDs are not available yet, connect will be happen
                 // upon arrival of the ACTION_UUID intent.
-                Log.d(TAG, "No profiles. Maybe we will connect later");
+                Log.d(TAG, "No profiles. Maybe we will connect later for device " + mDevice);
                 return;
             }
 
@@ -608,10 +610,12 @@
         long timeout = MAX_UUID_DELAY_FOR_AUTO_CONNECT;
         if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hogp)) {
             timeout = MAX_HOGP_DELAY_FOR_AUTO_CONNECT;
+        } else if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HearingAid)) {
+            timeout = MAX_HEARING_AIDS_DELAY_FOR_AUTO_CONNECT;
         }
 
         if (BluetoothUtils.D) {
-            Log.d(TAG, "onUuidChanged: Time since last connect"
+            Log.d(TAG, "onUuidChanged: Time since last connect="
                     + (SystemClock.elapsedRealtime() - mConnectAttempted));
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 1194a1d..d521809 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1316,7 +1316,11 @@
         } else if (oldState == StatusBarState.SHADE_LOCKED
                 && statusBarState == StatusBarState.KEYGUARD) {
             animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-            mQs.animateHeaderSlidingOut();
+            // Only animate header if the header is visible. If not, it will partially animate out
+            // the top of QS
+            if (!mQsExpanded) {
+                mQs.animateHeaderSlidingOut();
+            }
         } else {
             mKeyguardStatusBar.setAlpha(1f);
             mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index d350c3a..93168db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -661,7 +661,13 @@
     public boolean onBackPressed(boolean hideImmediately) {
         if (mBouncer.isShowing()) {
             mStatusBar.endAffordanceLaunch();
-            reset(hideImmediately);
+            // The second condition is for SIM card locked bouncer
+            if (mBouncer.isScrimmed() && !mBouncer.needsFullscreenBouncer()) {
+                hideBouncer(false);
+                updateStates();
+            } else {
+                reset(hideImmediately);
+            }
             return true;
         }
         return false;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 34702ec..d52fe81 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -3664,6 +3664,13 @@
                 }
             }
 
+            if (!mIgnoreSettingsPackageWhitelist.isEmpty()) {
+                pw.println("  Bypass Whitelisted Packages:");
+                for (String packageName : mIgnoreSettingsPackageWhitelist) {
+                    pw.println("    " + packageName);
+                }
+            }
+
             if (mLocationFudger != null) {
                 pw.append("  fudger: ");
                 mLocationFudger.dump(fd, pw, args);
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index d4c7ec3..da88ec5 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -239,9 +239,20 @@
         }, filter, null, getHandler());
     }
 
+    /**
+     * This method posts a blocking call to the handler thread, so it should not be called from
+     * that same thread.
+     * @throws {@link IllegalStateException} if called from {@link #mHandlerThread}
+     */
     @Override
     public ParceledListSlice getAvailableRollbacks() {
         enforceManageRollbacks("getAvailableRollbacks");
+        if (Thread.currentThread().equals(mHandlerThread)) {
+            Log.wtf(TAG, "Calling getAvailableRollbacks from mHandlerThread "
+                    + "causes a deadlock");
+            throw new IllegalStateException("Cannot call RollbackManager#getAvailableRollbacks "
+                    + "from the handler thread!");
+        }
 
         // Wait for the handler thread to get the list of available rollbacks
         // to get the most up-to-date results. This is intended to reduce test
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 0891ba4..9decb58 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -965,16 +965,13 @@
      * @param info
      * */
     private void startTraces(WindowingModeTransitionInfo info) {
-        if (info == null) {
+        if (!Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER) || info == null
+                || info.launchTraceActive) {
             return;
         }
-        int transitionType = getTransitionType(info);
-        if (!info.launchTraceActive && transitionType == TYPE_TRANSITION_WARM_LAUNCH
-                || transitionType == TYPE_TRANSITION_COLD_LAUNCH) {
-            Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: "
-                    + info.launchedActivity.packageName, 0);
-            info.launchTraceActive = true;
-        }
+        Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: "
+                + info.launchedActivity.packageName, 0);
+        info.launchTraceActive = true;
     }
 
     private void stopLaunchTrace(WindowingModeTransitionInfo info) {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index c4aef30..fe99fd2 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -3055,21 +3055,7 @@
         ActivityOptions.abort(options);
         if (DEBUG_STATES) Slog.d(TAG_STATES,
                 "resumeTopActivityInNextFocusableStack: " + reason + ", go home");
-        if (isActivityTypeHome()) {
-            // resumeTopActivityUncheckedLocked has been prevented to run recursively. Post a
-            // runnable to resume home since we are currently in the process of resuming top
-            // activity in home stack.
-            // See {@link #mInResumeTopActivity}.
-            mService.mH.post(
-                    () -> {
-                        synchronized (mService.mGlobalLock) {
-                            mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
-                        }
-                    });
-            return true;
-        } else {
-            return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
-        }
+        return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
     }
 
     /** Returns the position the input task should be placed in this stack. */
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 6a5c84a..652f7ee 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -90,6 +90,9 @@
 import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
 import static com.android.server.wm.DisplayContentProto.STACKS;
 import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER;
+import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
+import static com.android.server.wm.DisplayContentProto.CHANGING_APPS;
+import static com.android.server.wm.DisplayContentProto.CLOSING_APPS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
@@ -2736,6 +2739,15 @@
         if (mFocusedApp != null) {
             mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
         }
+        for (int i = mOpeningApps.size() - 1; i >= 0; i--) {
+            mOpeningApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, OPENING_APPS);
+        }
+        for (int i = mClosingApps.size() - 1; i >= 0; i--) {
+            mClosingApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, CLOSING_APPS);
+        }
+        for (int i = mChangingApps.size() - 1; i >= 0; i--) {
+            mChangingApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, CHANGING_APPS);
+        }
         proto.end(token);
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 26430fb..c23cdbb 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -2720,11 +2720,18 @@
     private void updateCurrentUserResources() {
         final int userId = mService.mAmInternal.getCurrentUserId();
         final Context uiContext = getSystemUiContext();
+
+        if (userId == UserHandle.USER_SYSTEM) {
+            // Skip the (expensive) recreation of resources for the system user below and just
+            // use the resources from the system ui context
+            mCurrentUserResources = uiContext.getResources();
+            return;
+        }
+
+        // For non-system users, ensure that the resources are loaded from the current
+        // user's package info (see ContextImpl.createDisplayContext)
         final LoadedApk pi = ActivityThread.currentActivityThread().getPackageInfo(
                 uiContext.getPackageName(), null, 0, userId);
-
-        // Create the resources from the current-user package info
-        // (see ContextImpl.createDisplayContext)
         mCurrentUserResources = ResourcesManager.getInstance().getResources(null,
                 pi.getResDir(),
                 null /* splitResDirs */,
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index be227e7..ed41642 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1906,7 +1906,8 @@
         if (this.meteredOverride != METERED_OVERRIDE_NONE) {
             sbuf.append(" meteredOverride ").append(meteredOverride).append("\n");
         }
-        sbuf.append(" macRandomizationSetting ").append(macRandomizationSetting).append("\n");
+        sbuf.append(" macRandomizationSetting: ").append(macRandomizationSetting).append("\n");
+        sbuf.append(" mRandomizedMacAddress: ").append(mRandomizedMacAddress).append("\n");
         sbuf.append(" KeyMgmt:");
         for (int k = 0; k < this.allowedKeyManagement.size(); k++) {
             if (this.allowedKeyManagement.get(k)) {