[Magnifier-23] Fix invisible cursor in magnifier

Previously, if the magnifier was triggered when the cursor was invisible
between blinks, the cursor would remain invisible until its position
first changed as a result of user dragging. This CL fixes this, by
forcing the cursor to become visible when the magnifier is triggered.

Test: manual testing
Test: atest CtsWidgetTestCases:android.widget.cts.TextViewTest
Test: atest FrameworksCoreTests:android.widget.TextViewActivityTest
Bug: 72314929
Bug: 63531115
Change-Id: I95dd0c2474f1cd1695ff3083e062ee38867b8a0c
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 892b8b6..2e7b2fd 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -262,7 +262,8 @@
     boolean mDiscardNextActionUp;
     boolean mIgnoreActionUpEvent;
 
-    long mShowCursor;
+    private long mShowCursor;
+    private boolean mRenderCursorRegardlessTiming;
     private Blink mBlink;
 
     boolean mCursorVisible = true;
@@ -681,11 +682,22 @@
         }
     }
 
-    boolean isCursorVisible() {
+    private boolean isCursorVisible() {
         // The default value is true, even when there is no associated Editor
         return mCursorVisible && mTextView.isTextEditable();
     }
 
+    boolean shouldRenderCursor() {
+        if (!isCursorVisible()) {
+            return false;
+        }
+        if (mRenderCursorRegardlessTiming) {
+            return true;
+        }
+        final long showCursorDelta = SystemClock.uptimeMillis() - mShowCursor;
+        return showCursorDelta % (2 * BLINK) < BLINK;
+    }
+
     void prepareCursorControllers() {
         boolean windowSupportsHandles = false;
 
@@ -4666,13 +4678,18 @@
                     + mTextView.getLayout().getLineBottom(lineNumber)) / 2.0f
                     + mTextView.getTotalPaddingTop() - mTextView.getScrollY();
 
+            // Make the cursor visible and stop blinking.
+            mRenderCursorRegardlessTiming = true;
+            mTextView.invalidateCursorPath();
             suspendBlink();
+
             mMagnifier.show(xPosInView, yPosInView);
         }
 
         protected final void dismissMagnifier() {
             if (mMagnifier != null) {
                 mMagnifier.dismiss();
+                mRenderCursorRegardlessTiming = false;
                 resumeBlink();
             }
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1e02c30..9ac5d59 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6965,9 +6965,7 @@
         final int selEnd = getSelectionEnd();
         if (mMovement != null && (isFocused() || isPressed()) && selStart >= 0) {
             if (selStart == selEnd) {
-                if (mEditor != null && mEditor.isCursorVisible()
-                        && (SystemClock.uptimeMillis() - mEditor.mShowCursor)
-                        % (2 * Editor.BLINK) < Editor.BLINK) {
+                if (mEditor != null && mEditor.shouldRenderCursor()) {
                     if (mHighlightPathBogus) {
                         if (mHighlightPath == null) mHighlightPath = new Path();
                         mHighlightPath.reset();