OSDN Git Service

DO NOT MERGE back porting for fixing sysui direct reply
[android-x86/frameworks-base.git] / core / java / android / widget / TextView.java
index 9a92489..d892307 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH;
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX;
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
@@ -28,11 +29,13 @@ import android.annotation.FloatRange;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.Size;
 import android.annotation.StringRes;
 import android.annotation.StyleRes;
 import android.annotation.XmlRes;
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.assist.AssistStructure;
 import android.content.ClipData;
 import android.content.ClipDescription;
@@ -66,6 +69,7 @@ import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.ParcelableParcel;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.BoringLayout;
 import android.text.DynamicLayout;
@@ -374,6 +378,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     private static final int KEY_DOWN_HANDLED_BY_KEY_LISTENER = 1;
     private static final int KEY_DOWN_HANDLED_BY_MOVEMENT_METHOD = 2;
 
+    private static final int FLOATING_TOOLBAR_SELECT_ALL_REFRESH_DELAY = 500;
+
     // System wide time for last cut, copy or text changed action.
     static long sLastCutCopyOrTextChangedTime;
 
@@ -684,6 +690,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
 
     private InputFilter[] mFilters = NO_FILTERS;
 
+    /**
+     * To keep the information to indicate if there is necessary to restrict the power of
+     * INTERACT_ACROSS_USERS_FULL.
+     * <p>
+     * SystemUI always run as user 0 to process all of direct reply. SystemUI has the poer of
+     * INTERACT_ACROSS_USERS_FULL. However, all of the notifications not only belong to user 0 but
+     * also to the other users in multiple user environment.
+     * </p>
+     *
+     * @see #setRestrictedAcrossUser(boolean)
+     */
+    private boolean mIsRestrictedAcrossUser;
+
     private volatile Locale mCurrentSpellCheckerLocaleCache;
 
     // It is possible to have a selection even when mEditor is null (programmatically set, like when
@@ -5674,7 +5693,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
         return mTransformation instanceof PasswordTransformationMethod;
     }
 
-    private static boolean isPasswordInputType(int inputType) {
+    static boolean isPasswordInputType(int inputType) {
         final int variation =
                 inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
         return variation
@@ -8339,7 +8358,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     }
 
     private boolean suggestedSizeFitsInSpace(int suggestedSizeInPx, RectF availableSpace) {
-        final CharSequence text = getText();
+        final CharSequence text = mTransformed != null
+                ? mTransformed
+                : getText();
         final int maxLines = getMaxLines();
         if (mTempTextPaint == null) {
             mTempTextPaint = new TextPaint();
@@ -8405,7 +8426,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
 
         if (mMaxMode != LINES) {
             desired = Math.min(desired, mMaximum);
-        } else if (cap && linecount > mMaximum && layout instanceof DynamicLayout) {
+        } else if (cap && linecount > mMaximum && (layout instanceof DynamicLayout
+                || layout instanceof BoringLayout)) {
             desired = layout.getLineTop(mMaximum);
 
             if (dr != null) {
@@ -9360,7 +9382,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
             }
         }
 
-        if (mEditor != null) mEditor.sendOnTextChanged(start, after);
+        if (mEditor != null) mEditor.sendOnTextChanged(start, before, after);
     }
 
     /**
@@ -10036,6 +10058,24 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     }
 
     /**
+     * To notify the TextView to restricted the power of the app granted INTERACT_ACROSS_USERS_FULL
+     * permission.
+     * <p>
+     * Most of applications should not granted the INTERACT_ACROSS_USERS_FULL permssion.
+     * SystemUI is the special one that run in user 0 process to handle multiple user notification.
+     * Unforunately, the power of INTERACT_ACROSS_USERS_FULL should be limited or restricted for
+     * preventing from information leak.</p>
+     * <p>This function call is called for SystemUI Keyguard and Notification.</p>
+     *
+     * @param isRestricted is true if the power of INTERACT_ACROSS_USERS_FULL should be limited.
+     * @hide
+     */
+    @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
+    public final void setRestrictedAcrossUser(boolean isRestricted) {
+        mIsRestrictedAcrossUser = isRestricted;
+    }
+
+    /**
      * This is a temporary method. Future versions may support multi-locale text.
      * Caveat: This method may not return the latest text services locale, but this should be
      * acceptable and it's more important to make this method asynchronous.
@@ -10318,7 +10358,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
             return;
         }
 
-        setText(value.getTextValue(), mBufferType, true, 0);
+        final CharSequence autofilledValue = value.getTextValue();
+
+        // First autofill it...
+        setText(autofilledValue, mBufferType, true, 0);
+
+        // ...then move cursor to the end.
+        final CharSequence text = getText();
+        if ((text instanceof Spannable)) {
+            Selection.setSelection((Spannable) text, text.length());
+        }
     }
 
     @Override
@@ -10862,6 +10911,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     @Override
     public boolean performLongClick() {
         boolean handled = false;
+        boolean performedHapticFeedback = false;
 
         if (mEditor != null) {
             mEditor.mIsBeingLongClicked = true;
@@ -10869,6 +10919,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
 
         if (super.performLongClick()) {
             handled = true;
+            performedHapticFeedback = true;
         }
 
         if (mEditor != null) {
@@ -10877,7 +10928,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
         }
 
         if (handled) {
-            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+            if (!performedHapticFeedback) {
+              performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+            }
             if (mEditor != null) mEditor.mDiscardNextActionUp = true;
         } else {
             MetricsLogger.action(
@@ -11055,6 +11108,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     }
 
     boolean canCut() {
+        if (mIsRestrictedAcrossUser
+                && UserHandle.myUserId() != ActivityManager.getCurrentUser()) {
+            // When it's restricted, and the curren user is not the process user. It can't cut
+            // because it may cut the text of the user 10 into the clipboard of user 0.
+            return false;
+        }
         if (hasPasswordTransformationMethod()) {
             return false;
         }
@@ -11068,6 +11127,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     }
 
     boolean canCopy() {
+        if (mIsRestrictedAcrossUser
+                && UserHandle.myUserId() != ActivityManager.getCurrentUser()) {
+            // When it's restricted, and the curren user is not the process user. It can't copy
+            // because it may copy the text of the user 10 to the clipboard of user 0.
+            return false;
+        }
         if (hasPasswordTransformationMethod()) {
             return false;
         }
@@ -11097,6 +11162,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     }
 
     boolean canPaste() {
+        if (mIsRestrictedAcrossUser
+                && UserHandle.myUserId() != ActivityManager.getCurrentUser()) {
+            // When it's restricted, and the curren user is not the process user. It can't paste
+            // because it may copy the text from the user 0 clipboard in current user is 10.
+            return false;
+        }
         return (mText instanceof Editable
                 && mEditor != null && mEditor.mKeyListener != null
                 && getSelectionStart() >= 0
@@ -11138,6 +11209,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     }
 
     boolean selectAllText() {
+        if (mEditor != null) {
+            // Hide the toolbar before changing the selection to avoid flickering.
+            mEditor.hideFloatingToolbar(FLOATING_TOOLBAR_SELECT_ALL_REFRESH_DELAY);
+        }
         final int length = mText.length();
         Selection.setSelection((Spannable) mText, 0, length);
         return length > 0;