Merge "Fix suggestion popup for RTL text on LTR layout." into nyc-dev
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index 878b7a0..3c7c962 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -231,6 +231,18 @@
         mAsynchronous = async;
     }
 
+    /** {@hide} */
+    public String getTraceName(Message message) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getName()).append(": ");
+        if (message.callback != null) {
+            sb.append(message.callback.getClass().getName());
+        } else {
+            sb.append("#").append(message.what);
+        }
+        return sb.toString();
+    }
+
     /**
      * Returns a string representing the name of the specified message.
      * The default implementation will either return the class name of the
@@ -739,8 +751,8 @@
         message.callback.run();
     }
 
-    final MessageQueue mQueue;
     final Looper mLooper;
+    final MessageQueue mQueue;
     final Callback mCallback;
     final boolean mAsynchronous;
     IMessenger mMessenger;
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 34c880f..b58ff1f 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -72,6 +72,7 @@
     final Thread mThread;
 
     private Printer mLogging;
+    private long mTraceTag;
 
      /** Initialize the current thread as a looper.
       * This gives you a chance to create handlers that then reference
@@ -139,13 +140,23 @@
             }
 
             // This must be in a local variable, in case a UI event sets the logger
-            Printer logging = me.mLogging;
+            final Printer logging = me.mLogging;
             if (logging != null) {
                 logging.println(">>>>> Dispatching to " + msg.target + " " +
                         msg.callback + ": " + msg.what);
             }
 
-            msg.target.dispatchMessage(msg);
+            final long traceTag = me.mTraceTag;
+            if (traceTag != 0) {
+                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
+            }
+            try {
+                msg.target.dispatchMessage(msg);
+            } finally {
+                if (traceTag != 0) {
+                    Trace.traceEnd(traceTag);
+                }
+            }
 
             if (logging != null) {
                 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
@@ -208,6 +219,11 @@
         mLogging = printer;
     }
 
+    /** {@hide} */
+    public void setTraceTag(long traceTag) {
+        mTraceTag = traceTag;
+    }
+
     /**
      * Quits the looper.
      * <p>
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 5e7fc70..440ef21 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1778,6 +1778,18 @@
         if (translate) canvas.translate(0, -cursorOffsetVertical);
     }
 
+    void invalidateHandlesAndActionMode() {
+        if (mSelectionModifierCursorController != null) {
+            mSelectionModifierCursorController.invalidateHandles();
+        }
+        if (mInsertionPointCursorController != null) {
+            mInsertionPointCursorController.invalidateHandle();
+        }
+        if (mTextActionMode != null) {
+            mTextActionMode.invalidate();
+        }
+    }
+
     /**
      * Invalidates all the sub-display lists that overlap the specified character range
      */
@@ -4103,6 +4115,14 @@
             setMeasuredDimension(getPreferredWidth(), getPreferredHeight());
         }
 
+        @Override
+        public void invalidate() {
+            super.invalidate();
+            if (isShowing()) {
+                positionAtCursorOffset(getCurrentCursorOffset(), true);
+            }
+        };
+
         private int getPreferredWidth() {
             return Math.max(mDrawable.getIntrinsicWidth(), mMinSize);
         }
@@ -4169,7 +4189,12 @@
             return mTextView.getOffsetAtCoordinate(line, x);
         }
 
-        protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
+        /**
+         * @param offset Cursor offset. Must be in [-1, length].
+         * @param forceUpdatePosition whether to force update the position.  This should be true
+         * when If the parent has been scrolled, for example.
+         */
+        protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) {
             // A HandleView relies on the layout, which may be nulled by external methods
             Layout layout = mTextView.getLayout();
             if (layout == null) {
@@ -4180,7 +4205,7 @@
             layout = mTextView.getLayout();
 
             boolean offsetChanged = offset != mPreviousOffset;
-            if (offsetChanged || parentScrolled) {
+            if (offsetChanged || forceUpdatePosition) {
                 if (offsetChanged) {
                     updateSelection(offset);
                     addPositionToTouchUpFilter(offset);
@@ -4781,13 +4806,9 @@
             mPrevX = x;
         }
 
-        /**
-         * @param offset Cursor offset. Must be in [-1, length].
-         * @param parentScrolled If the parent has been scrolled or not.
-         */
         @Override
-        protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
-            super.positionAtCursorOffset(offset, parentScrolled);
+        protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) {
+            super.positionAtCursorOffset(offset, forceUpdatePosition);
             mInWord = (offset != -1) && !getWordIteratorWithText().isBoundary(offset);
         }
 
@@ -5013,6 +5034,12 @@
         public boolean isActive() {
             return mHandle != null && mHandle.isShowing();
         }
+
+        public void invalidateHandle() {
+            if (mHandle != null) {
+                mHandle.invalidate();
+            }
+        }
     }
 
     class SelectionModifierCursorController implements CursorController {
@@ -5417,6 +5444,15 @@
         public boolean isActive() {
             return mStartHandle != null && mStartHandle.isShowing();
         }
+
+        public void invalidateHandles() {
+            if (mStartHandle != null) {
+                mStartHandle.invalidate();
+            }
+            if (mEndHandle != null) {
+                mEndHandle.invalidate();
+            }
+        }
     }
 
     private class CorrectionHighlighter {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 4483b7ba..48fd58b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3350,7 +3350,10 @@
         mShadowColor = color;
 
         // Will change text clip region
-        if (mEditor != null) mEditor.invalidateTextDisplayList();
+        if (mEditor != null) {
+            mEditor.invalidateTextDisplayList();
+            mEditor.invalidateHandlesAndActionMode();
+        }
         invalidate();
     }
 
@@ -8306,6 +8309,7 @@
             if (mEditor != null) {
                 if (oldStart >= 0) mEditor.invalidateTextDisplayList(mLayout, oldStart, oldEnd);
                 if (newStart >= 0) mEditor.invalidateTextDisplayList(mLayout, newStart, newEnd);
+                mEditor.invalidateHandlesAndActionMode();
             }
         }
 
diff --git a/core/java/com/android/internal/os/BackgroundThread.java b/core/java/com/android/internal/os/BackgroundThread.java
index d6f7b20..cffba01 100644
--- a/core/java/com/android/internal/os/BackgroundThread.java
+++ b/core/java/com/android/internal/os/BackgroundThread.java
@@ -18,6 +18,7 @@
 
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.Trace;
 
 /**
  * Shared singleton background thread for each process.
@@ -34,6 +35,7 @@
         if (sInstance == null) {
             sInstance = new BackgroundThread();
             sInstance.start();
+            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             sHandler = new Handler(sInstance.getLooper());
         }
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
index c7d60e3..f239eb4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/State.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -123,9 +123,6 @@
     /** Instance state for every shown directory */
     public HashMap<String, SparseArray<Parcelable>> dirState = new HashMap<>();
 
-    /** UI selection */
-    public Selection selectedDocuments = new Selection();
-
     /** Currently copying file */
     public List<DocumentInfo> selectedDocumentsForCopy = new ArrayList<>();
 
@@ -202,7 +199,6 @@
         out.writeInt(external ? 1 : 0);
         DurableUtils.writeToParcel(out, stack);
         out.writeMap(dirState);
-        out.writeParcelable(selectedDocuments, 0);
         out.writeList(selectedDocumentsForCopy);
         out.writeList(excludedAuthorities);
         out.writeInt(openableOnly ? 1 : 0);
@@ -233,7 +229,6 @@
             state.external = in.readInt() != 0;
             DurableUtils.readFromParcel(in, state.stack);
             in.readMap(state.dirState, loader);
-            state.selectedDocuments = in.readParcelable(loader);
             in.readList(state.selectedDocumentsForCopy, loader);
             in.readList(state.excludedAuthorities, loader);
             state.openableOnly = in.readInt() != 0;
diff --git a/services/core/java/com/android/server/DisplayThread.java b/services/core/java/com/android/server/DisplayThread.java
index aa0a805..9ef0259 100644
--- a/services/core/java/com/android/server/DisplayThread.java
+++ b/services/core/java/com/android/server/DisplayThread.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.os.Handler;
+import android.os.Trace;
 
 /**
  * Shared singleton foreground thread for the system.  This is a thread for
@@ -36,6 +37,7 @@
         if (sInstance == null) {
             sInstance = new DisplayThread();
             sInstance.start();
+            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             sHandler = new Handler(sInstance.getLooper());
         }
     }
diff --git a/services/core/java/com/android/server/FgThread.java b/services/core/java/com/android/server/FgThread.java
index 03765db..5f85cba 100644
--- a/services/core/java/com/android/server/FgThread.java
+++ b/services/core/java/com/android/server/FgThread.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.os.Handler;
+import android.os.Trace;
 
 /**
  * Shared singleton foreground thread for the system.  This is a thread for regular
@@ -38,6 +39,7 @@
         if (sInstance == null) {
             sInstance = new FgThread();
             sInstance.start();
+            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             sHandler = new Handler(sInstance.getLooper());
         }
     }
diff --git a/services/core/java/com/android/server/IoThread.java b/services/core/java/com/android/server/IoThread.java
index 0f29857..ad4c194 100644
--- a/services/core/java/com/android/server/IoThread.java
+++ b/services/core/java/com/android/server/IoThread.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.os.Handler;
+import android.os.Trace;
 
 /**
  * Shared singleton I/O thread for the system.  This is a thread for non-background
@@ -35,6 +36,7 @@
         if (sInstance == null) {
             sInstance = new IoThread();
             sInstance.start();
+            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             sHandler = new Handler(sInstance.getLooper());
         }
     }
diff --git a/services/core/java/com/android/server/UiThread.java b/services/core/java/com/android/server/UiThread.java
index 0beb77f..c06afc2 100644
--- a/services/core/java/com/android/server/UiThread.java
+++ b/services/core/java/com/android/server/UiThread.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.os.Handler;
+import android.os.Trace;
 
 /**
  * Shared singleton thread for showing UI.  This is a foreground thread, and in
@@ -35,6 +36,7 @@
         if (sInstance == null) {
             sInstance = new UiThread();
             sInstance.start();
+            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             sHandler = new Handler(sInstance.getLooper());
         }
     }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f659bde..7b2a370 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2043,8 +2043,10 @@
             resizeStackUncheckedLocked(stack, dockedBounds, tempDockedTaskBounds,
                     tempDockedTaskInsetBounds);
 
-            if (stack.mFullscreen) {
-                // The dock stack went fullscreen which is kinda like dismissing it.
+            // TODO: Checking for isAttached might not be needed as if the user passes in null
+            // dockedBounds then they want the docked stack to be dismissed.
+            if (stack.mFullscreen || (dockedBounds == null && !stack.isAttached())) {
+                // The dock stack either was dismissed or went fullscreen, which is kinda the same.
                 // In this case we make all other static stacks fullscreen and move all
                 // docked stack tasks to the fullscreen stack.
                 for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
@@ -2069,18 +2071,13 @@
                 // static stacks need to be adjusted so they don't overlap with the docked stack.
                 // We get the bounds to use from window manager which has been adjusted for any
                 // screen controls and is also the same for all stacks.
-                if (dockedBounds != null) {
-                    mWindowManager.getStackDockedModeBounds(
-                            HOME_STACK_ID, tempRect, true /* ignoreVisibility */);
-                }
+                mWindowManager.getStackDockedModeBounds(
+                        HOME_STACK_ID, tempRect, true /* ignoreVisibility */);
                 for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
-                    if (StackId.isResizeableByDockedStack(i)) {
-                        ActivityStack otherStack = getStack(i);
-                        if (otherStack != null) {
-                            resizeStackLocked(i, dockedBounds != null ? tempRect : null,
-                                    tempOtherTaskBounds, tempOtherTaskInsetBounds, preserveWindows,
-                                    true /* allowResizeInDockedMode */);
-                        }
+                    if (StackId.isResizeableByDockedStack(i) && getStack(i) != null) {
+                        resizeStackLocked(i, tempRect, tempOtherTaskBounds,
+                                tempOtherTaskInsetBounds, preserveWindows,
+                                true /* allowResizeInDockedMode */);
                     }
                 }
             }