summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yohei Yukawa <yukawa@google.com> 2019-01-21 09:24:26 -0800
committer Yohei Yukawa <yukawa@google.com> 2019-01-21 09:24:26 -0800
commit17ace29a10c8eaa5553acad0ebb62aee3efbd303 (patch)
tree2658b16a1f635392e2e5eb8414f9912b6ec71002
parentd3e0fd9395151fa031661d56d9c13c9e7cc8d2b4 (diff)
Deprecate SuggestionSpan#ACTION_SUGGESTION_PICKED
This CL deprecates SuggestionSpan#ACTION_SUGGESTION_PICKED and related constants [1]. There are multiple security concerns, open questions about compatibility, and maintainance challanges in this protocol. IME developers can implement their own suggestion picker UI on top of CursorAnchorInfo API to achieve safer, should give more flexible UI options, better security, and better compatibility. [1]: Ia539de0acf66053e0349daec459d75e36805f6bf f9f01008624e2d28c15a90d942fa36f98c8c967d Fix: 123160396 Test: make -j checkbuild Change-Id: I6d39e838ae47488055162cd44b5f553f68869b17
-rw-r--r--api/current.txt8
-rw-r--r--core/java/android/text/style/SuggestionSpan.java102
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java30
-rw-r--r--core/java/android/widget/Editor.java4
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl3
-rw-r--r--core/java/com/android/internal/widget/EditableInputConnection.java8
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java48
-rw-r--r--services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java15
8 files changed, 64 insertions, 154 deletions
diff --git a/api/current.txt b/api/current.txt
index 6122e5208985..d58b76ff76fb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -46827,15 +46827,15 @@ package android.text.style {
method public void setFlags(int);
method public void updateDrawState(android.text.TextPaint);
method public void writeToParcel(android.os.Parcel, int);
- field public static final String ACTION_SUGGESTION_PICKED = "android.text.style.SUGGESTION_PICKED";
+ field @Deprecated public static final String ACTION_SUGGESTION_PICKED = "android.text.style.SUGGESTION_PICKED";
field public static final android.os.Parcelable.Creator<android.text.style.SuggestionSpan> CREATOR;
field public static final int FLAG_AUTO_CORRECTION = 4; // 0x4
field public static final int FLAG_EASY_CORRECT = 1; // 0x1
field public static final int FLAG_MISSPELLED = 2; // 0x2
field public static final int SUGGESTIONS_MAX_SIZE = 5; // 0x5
- field public static final String SUGGESTION_SPAN_PICKED_AFTER = "after";
- field public static final String SUGGESTION_SPAN_PICKED_BEFORE = "before";
- field public static final String SUGGESTION_SPAN_PICKED_HASHCODE = "hashcode";
+ field @Deprecated public static final String SUGGESTION_SPAN_PICKED_AFTER = "after";
+ field @Deprecated public static final String SUGGESTION_SPAN_PICKED_BEFORE = "before";
+ field @Deprecated public static final String SUGGESTION_SPAN_PICKED_HASHCODE = "hashcode";
}
public class SuperscriptSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 7a586815199c..dd073e9142b1 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -21,7 +21,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Parcel;
@@ -31,7 +30,6 @@ import android.text.ParcelableSpan;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.Log;
-import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import java.util.Arrays;
@@ -72,9 +70,37 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
*/
public static final int FLAG_AUTO_CORRECTION = 0x0004;
+ /**
+ * This action is deprecated in {@link android.os.Build.VERSION_CODES#Q}.
+ *
+ * @deprecated For IMEs to receive this kind of user interaction signals, implement IMEs' own
+ * suggestion picker UI instead of relying on {@link SuggestionSpan}. To retrieve
+ * bounding boxes for each character of the composing text, use
+ * {@link android.view.inputmethod.CursorAnchorInfo}.
+ */
+ @Deprecated
public static final String ACTION_SUGGESTION_PICKED = "android.text.style.SUGGESTION_PICKED";
+
+ /**
+ * This is deprecated in {@link android.os.Build.VERSION_CODES#Q}.
+ *
+ * @deprecated See {@link #ACTION_SUGGESTION_PICKED}.
+ */
+ @Deprecated
public static final String SUGGESTION_SPAN_PICKED_AFTER = "after";
+ /**
+ * This is deprecated in {@link android.os.Build.VERSION_CODES#Q}.
+ *
+ * @deprecated See {@link #ACTION_SUGGESTION_PICKED}.
+ */
+ @Deprecated
public static final String SUGGESTION_SPAN_PICKED_BEFORE = "before";
+ /**
+ * This is deprecated in {@link android.os.Build.VERSION_CODES#Q}.
+ *
+ * @deprecated See {@link #ACTION_SUGGESTION_PICKED}.
+ */
+ @Deprecated
public static final String SUGGESTION_SPAN_PICKED_HASHCODE = "hashcode";
public static final int SUGGESTIONS_MAX_SIZE = 5;
@@ -97,8 +123,6 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
private final String mLocaleStringForCompatibility;
@NonNull
private final String mLanguageTag;
- private final String mNotificationTargetClassName;
- private final String mNotificationTargetPackageName;
private final int mHashCode;
@UnsupportedAppUsage
@@ -137,7 +161,9 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
* {@link SuggestionSpan#SUGGESTIONS_MAX_SIZE} will be considered. Null values not permitted.
* @param flags Additional flags indicating how this span is handled in TextView
* @param notificationTargetClass if not null, this class will get notified when the user
- * selects one of the suggestions.
+ * selects one of the suggestions. On Android
+ * {@link android.os.Build.VERSION_CODES#Q} and later this
+ * parameter is always ignored.
*/
public SuggestionSpan(Context context, Locale locale, String[] suggestions, int flags,
Class<?> notificationTargetClass) {
@@ -156,20 +182,7 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
}
mLocaleStringForCompatibility = sourceLocale == null ? "" : sourceLocale.toString();
mLanguageTag = sourceLocale == null ? "" : sourceLocale.toLanguageTag();
-
- if (context != null) {
- mNotificationTargetPackageName = context.getPackageName();
- } else {
- mNotificationTargetPackageName = null;
- }
-
- if (notificationTargetClass != null) {
- mNotificationTargetClassName = notificationTargetClass.getCanonicalName();
- } else {
- mNotificationTargetClassName = "";
- }
- mHashCode = hashCodeInternal(mSuggestions, mLanguageTag, mLocaleStringForCompatibility,
- mNotificationTargetClassName);
+ mHashCode = hashCodeInternal(mSuggestions, mLanguageTag, mLocaleStringForCompatibility);
initStyle(context);
}
@@ -215,8 +228,6 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
mFlags = src.readInt();
mLocaleStringForCompatibility = src.readString();
mLanguageTag = src.readString();
- mNotificationTargetClassName = src.readString();
- mNotificationTargetPackageName = src.readString();
mHashCode = src.readInt();
mEasyCorrectUnderlineColor = src.readInt();
mEasyCorrectUnderlineThickness = src.readFloat();
@@ -260,17 +271,15 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
}
/**
- * @return The name of the class to notify. The class of the original IME package will receive
- * a notification when the user selects one of the suggestions. The notification will include
- * the original string, the suggested replacement string as well as the hashCode of this span.
- * The class will get notified by an intent that has those information.
- * This is an internal API because only the framework should know the class name.
+ * @return {@code null}.
*
* @hide
+ * @deprecated Do not use. Always returns {@code null}.
*/
+ @Deprecated
@UnsupportedAppUsage
public String getNotificationTargetClassName() {
- return mNotificationTargetClassName;
+ return null;
}
public int getFlags() {
@@ -297,8 +306,6 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
dest.writeInt(mFlags);
dest.writeString(mLocaleStringForCompatibility);
dest.writeString(mLanguageTag);
- dest.writeString(mNotificationTargetClassName);
- dest.writeString(mNotificationTargetPackageName);
dest.writeInt(mHashCode);
dest.writeInt(mEasyCorrectUnderlineColor);
dest.writeFloat(mEasyCorrectUnderlineThickness);
@@ -332,9 +339,9 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
}
private static int hashCodeInternal(String[] suggestions, @NonNull String languageTag,
- @NonNull String localeStringForCompatibility, String notificationTargetClassName) {
+ @NonNull String localeStringForCompatibility) {
return Arrays.hashCode(new Object[] {Long.valueOf(SystemClock.uptimeMillis()), suggestions,
- languageTag, localeStringForCompatibility, notificationTargetClassName});
+ languageTag, localeStringForCompatibility});
}
public static final Parcelable.Creator<SuggestionSpan> CREATOR =
@@ -390,39 +397,14 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
}
/**
- * Notifies a suggestion selection.
+ * Does nothing.
*
+ * @deprecated this is deprecated in {@link android.os.Build.VERSION_CODES#Q}.
* @hide
*/
@UnsupportedAppUsage
+ @Deprecated
public void notifySelection(Context context, String original, int index) {
- final Intent intent = new Intent();
-
- if (context == null || mNotificationTargetClassName == null) {
- return;
- }
- // Ensures that only a class in the original IME package will receive the
- // notification.
- if (mSuggestions == null || index < 0 || index >= mSuggestions.length) {
- Log.w(TAG, "Unable to notify the suggestion as the index is out of range index=" + index
- + " length=" + mSuggestions.length);
- return;
- }
-
- // The package name is not mandatory (legacy from JB), and if the package name
- // is missing, we try to notify the suggestion through the input method manager.
- if (mNotificationTargetPackageName != null) {
- intent.setClassName(mNotificationTargetPackageName, mNotificationTargetClassName);
- intent.setAction(SuggestionSpan.ACTION_SUGGESTION_PICKED);
- intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE, original);
- intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER, mSuggestions[index]);
- intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_HASHCODE, hashCode());
- context.sendBroadcast(intent);
- } else {
- InputMethodManager imm = context.getSystemService(InputMethodManager.class);
- if (imm != null) {
- imm.notifySuggestionPicked(this, original, index);
- }
- }
+ Log.w(TAG, "notifySelection() is deprecated. Does nothing.");
}
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 1ba7d8ed5db2..86c5f188ffab 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -980,24 +980,30 @@ public final class InputMethodManager {
InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(null, 0);
}
- /** @hide */
+ /**
+ * This hidden API is deprecated in {@link android.os.Build.VERSION_CODES#Q}. Does nothing.
+ *
+ * @param spans will be ignored.
+ *
+ * @deprecated Do not use.
+ * @hide
+ */
+ @Deprecated
@UnsupportedAppUsage
public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
- try {
- mService.registerSuggestionSpansForNotification(spans);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ Log.w(TAG, "registerSuggestionSpansForNotification() is deprecated. Does nothing.");
}
- /** @hide */
+ /**
+ * This hidden API is deprecated in {@link android.os.Build.VERSION_CODES#Q}. Does nothing.
+ *
+ * @deprecated Do not use.
+ * @hide
+ */
+ @Deprecated
@UnsupportedAppUsage
public void notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
- try {
- mService.notifySuggestionPicked(span, originalString, index);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ Log.w(TAG, "notifySuggestionPicked() is deprecated. Does nothing.");
}
/**
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 55364ec1017d..4a60b6a8185a 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2901,10 +2901,6 @@ public class Editor {
}
}
- // Notify source IME of the suggestion pick. Do this before swapping texts.
- targetSuggestionSpan.notifySelection(
- mTextView.getContext(), originalText, suggestionInfo.mSuggestionIndex);
-
// Swap text content between actual text and Suggestion span
final int suggestionStart = suggestionInfo.mSuggestionStart;
final int suggestionEnd = suggestionInfo.mSuggestionEnd;
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 70f4ed2d529e..356d178cc4eb 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -17,7 +17,6 @@
package com.android.internal.view;
import android.os.ResultReceiver;
-import android.text.style.SuggestionSpan;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.EditorInfo;
@@ -65,8 +64,6 @@ interface IInputMethodManager {
int displayId);
void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId);
boolean isInputMethodPickerShownForTest();
- void registerSuggestionSpansForNotification(in SuggestionSpan[] spans);
- boolean notifySuggestionPicked(in SuggestionSpan span, String originalString, int index);
InputMethodSubtype getCurrentInputMethodSubtype();
boolean setCurrentInputMethodSubtype(in InputMethodSubtype subtype);
void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index 7f7528dd3de0..78688edb3f88 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -18,9 +18,7 @@ package com.android.internal.widget;
import android.os.Bundle;
import android.text.Editable;
-import android.text.Spanned;
import android.text.method.KeyListener;
-import android.text.style.SuggestionSpan;
import android.util.Log;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
@@ -173,12 +171,6 @@ public class EditableInputConnection extends BaseInputConnection {
if (mTextView == null) {
return super.commitText(text, newCursorPosition);
}
- if (text instanceof Spanned) {
- Spanned spanned = ((Spanned) text);
- SuggestionSpan[] spans = spanned.getSpans(0, text.length(), SuggestionSpan.class);
- mIMM.registerSuggestionSpansForNotification(spans);
- }
-
mTextView.resetErrorChangedFlag();
boolean success = super.commitText(text, newCursorPosition);
mTextView.hideErrorIfUnchanged();
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 0210da3e2160..6c3cc58a1bd6 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2513,54 +2513,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
- @Override
- public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
- synchronized (mMethodMap) {
- if (!calledFromValidUserLocked(!PER_PROFILE_IME_ENABLED)) {
- return;
- }
- final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
- for (int i = 0; i < spans.length; ++i) {
- SuggestionSpan ss = spans[i];
- if (!TextUtils.isEmpty(ss.getNotificationTargetClassName())) {
- mSecureSuggestionSpans.put(ss, currentImi);
- }
- }
- }
- }
-
- @Override
- public boolean notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
- synchronized (mMethodMap) {
- if (!calledFromValidUserLocked(!PER_PROFILE_IME_ENABLED)) {
- return false;
- }
- final InputMethodInfo targetImi = mSecureSuggestionSpans.get(span);
- // TODO: Do not send the intent if the process of the targetImi is already dead.
- if (targetImi != null) {
- final String[] suggestions = span.getSuggestions();
- if (index < 0 || index >= suggestions.length) return false;
- final String className = span.getNotificationTargetClassName();
- final Intent intent = new Intent();
- // Ensures that only a class in the original IME package will receive the
- // notification.
- intent.setClassName(targetImi.getPackageName(), className);
- intent.setAction(SuggestionSpan.ACTION_SUGGESTION_PICKED);
- intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE, originalString);
- intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER, suggestions[index]);
- intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_HASHCODE, span.hashCode());
- final long ident = Binder.clearCallingIdentity();
- try {
- mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- return true;
- }
- }
- return false;
- }
-
void updateFromSettingsLocked(boolean enabledMayChange) {
updateInputMethodsFromSettingsLocked(enabledMayChange);
updateKeyboardFromSettingsLocked();
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index f304cebddb25..6f0c5e83b4fe 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -53,7 +53,6 @@ import android.os.ShellCallback;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
-import android.text.style.SuggestionSpan;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -1525,20 +1524,6 @@ public final class MultiClientInputMethodManagerService {
@BinderThread
@Override
- public void registerSuggestionSpansForNotification(SuggestionSpan[] suggestionSpans) {
- reportNotSupported();
- }
-
- @BinderThread
- @Override
- public boolean notifySuggestionPicked(
- SuggestionSpan span, String originalString, int index) {
- reportNotSupported();
- return false;
- }
-
- @BinderThread
- @Override
public InputMethodSubtype getCurrentInputMethodSubtype() {
reportNotSupported();
return null;