Fix internal variables and equals in SuggestionSpan
Bug: 4443922
- Instantiating other package's class for the name is complicated, so we changed the internal value for the notification target class from Class to String.
- Implement equals
Change-Id: Iaf7682be777f0027d33c9a3be4609ac01b6950ad
diff --git a/api/current.txt b/api/current.txt
index 94e4210..2f5b9b4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -19386,7 +19386,6 @@
method public int describeContents();
method public int getFlags();
method public java.lang.String getLocale();
- method public java.lang.Class<?> getNotificationTargetClass();
method public int getSpanTypeId();
method public java.lang.String[] getSuggestions();
method public void writeToParcel(android.os.Parcel, int);
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index effa5c8..240ad9b 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -22,7 +22,6 @@
import android.os.SystemClock;
import android.text.ParcelableSpan;
import android.text.TextUtils;
-import android.util.Log;
import java.util.Arrays;
import java.util.Locale;
@@ -31,8 +30,6 @@
* Holds suggestion candidates of words under this span.
*/
public class SuggestionSpan implements ParcelableSpan {
- private static final String TAG = SuggestionSpan.class.getSimpleName();
-
/**
* Flag for indicating that the input is verbatim. TextView refers to this flag to determine
* how it displays a word with SuggestionSpan.
@@ -56,7 +53,7 @@
private final int mFlags;
private final String[] mSuggestions;
private final String mLocaleString;
- private final Class<?> mNotificationTargetClass;
+ private final String mNotificationTargetClassName;
private final int mHashCode;
/*
@@ -100,25 +97,20 @@
} else {
mLocaleString = locale.toString();
}
- mNotificationTargetClass = notificationTargetClass;
+ if (notificationTargetClass != null) {
+ mNotificationTargetClassName = notificationTargetClass.getCanonicalName();
+ } else {
+ mNotificationTargetClassName = "";
+ }
mHashCode = hashCodeInternal(
- mFlags, mSuggestions, mLocaleString, mNotificationTargetClass);
+ mFlags, mSuggestions, mLocaleString, mNotificationTargetClassName);
}
public SuggestionSpan(Parcel src) {
mSuggestions = src.readStringArray();
mFlags = src.readInt();
mLocaleString = src.readString();
- Class<?> tempClass = null;
- try {
- final String className = src.readString();
- if (!TextUtils.isEmpty(className)) {
- tempClass = Class.forName(className);
- }
- } catch (ClassNotFoundException e) {
- Log.i(TAG, "Invalid class name was created.");
- }
- mNotificationTargetClass = tempClass;
+ mNotificationTargetClassName = src.readString();
mHashCode = src.readInt();
}
@@ -137,13 +129,16 @@
}
/**
- * @return The class to notify. The class of the original IME package will receive
+ * @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.
+ *
+ * @hide
*/
- public Class<?> getNotificationTargetClass() {
- return mNotificationTargetClass;
+ public String getNotificationTargetClassName() {
+ return mNotificationTargetClassName;
}
public int getFlags() {
@@ -160,9 +155,7 @@
dest.writeStringArray(mSuggestions);
dest.writeInt(mFlags);
dest.writeString(mLocaleString);
- dest.writeString(mNotificationTargetClass != null
- ? mNotificationTargetClass.getCanonicalName()
- : "");
+ dest.writeString(mNotificationTargetClassName);
dest.writeInt(mHashCode);
}
@@ -172,17 +165,22 @@
}
@Override
+ public boolean equals(Object o) {
+ if (o instanceof SuggestionSpan) {
+ return ((SuggestionSpan)o).hashCode() == mHashCode;
+ }
+ return false;
+ }
+
+ @Override
public int hashCode() {
return mHashCode;
}
private static int hashCodeInternal(int flags, String[] suggestions,String locale,
- Class<?> notificationTargetClass) {
- final String cls = notificationTargetClass != null
- ? notificationTargetClass.getCanonicalName()
- : "";
- return Arrays.hashCode(
- new Object[] {SystemClock.uptimeMillis(), flags, suggestions, locale, cls});
+ String notificationTargetClassName) {
+ return Arrays.hashCode(new Object[] {SystemClock.uptimeMillis(), flags, suggestions, locale,
+ notificationTargetClassName});
}
public static final Parcelable.Creator<SuggestionSpan> CREATOR =
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 7361ef7..465fd2e 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1021,8 +1021,9 @@
final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
for (int i = 0; i < spans.length; ++i) {
SuggestionSpan ss = spans[i];
- if (ss.getNotificationTargetClass() != null) {
+ if (!TextUtils.isEmpty(ss.getNotificationTargetClassName())) {
mSecureSuggestionSpans.put(ss, currentImi);
+ final InputMethodInfo targetImi = mSecureSuggestionSpans.get(ss);
}
}
}
@@ -1035,11 +1036,11 @@
if (targetImi != null) {
final String[] suggestions = span.getSuggestions();
if (index < 0 || index >= suggestions.length) return false;
- final Class<?> c = span.getNotificationTargetClass();
+ 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(), c.getCanonicalName());
+ 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]);
@@ -1145,6 +1146,7 @@
}
}
+ @Override
public boolean showSoftInput(IInputMethodClient client, int flags,
ResultReceiver resultReceiver) {
int uid = Binder.getCallingUid();
@@ -1210,6 +1212,7 @@
return res;
}
+ @Override
public boolean hideSoftInput(IInputMethodClient client, int flags,
ResultReceiver resultReceiver) {
int uid = Binder.getCallingUid();
@@ -1272,6 +1275,7 @@
return res;
}
+ @Override
public void windowGainedFocus(IInputMethodClient client, IBinder windowToken,
boolean viewHasFocus, boolean isTextEditor, int softInputMode,
boolean first, int windowFlags) {
@@ -1373,6 +1377,7 @@
}
}
+ @Override
public void showInputMethodPickerFromClient(IInputMethodClient client) {
synchronized (mMethodMap) {
if (mCurClient == null || client == null
@@ -1387,10 +1392,12 @@
}
}
+ @Override
public void setInputMethod(IBinder token, String id) {
setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID);
}
+ @Override
public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
synchronized (mMethodMap) {
if (subtype != null) {
@@ -1402,6 +1409,7 @@
}
}
+ @Override
public void showInputMethodAndSubtypeEnablerFromClient(
IInputMethodClient client, String inputMethodId) {
synchronized (mMethodMap) {
@@ -1524,6 +1532,7 @@
}
}
+ @Override
public void hideMySoftInput(IBinder token, int flags) {
synchronized (mMethodMap) {
if (token == null || mCurToken != token) {
@@ -1540,6 +1549,7 @@
}
}
+ @Override
public void showMySoftInput(IBinder token, int flags) {
synchronized (mMethodMap) {
if (token == null || mCurToken != token) {
@@ -1576,6 +1586,7 @@
}
}
+ @Override
public boolean handleMessage(Message msg) {
HandlerCaller.SomeArgs args;
switch (msg.what) {
@@ -1919,6 +1930,7 @@
}
AlertDialog.OnClickListener adocl = new AlertDialog.OnClickListener() {
+ @Override
public void onClick(DialogInterface dialog, int which) {
hideInputMethodMenu();
}
@@ -1930,6 +1942,7 @@
mDialogBuilder = new AlertDialog.Builder(context)
.setTitle(com.android.internal.R.string.select_input_method)
.setOnCancelListener(new OnCancelListener() {
+ @Override
public void onCancel(DialogInterface dialog) {
hideInputMethodMenu();
}
@@ -1940,6 +1953,7 @@
mDialogBuilder.setSingleChoiceItems(mItems, checkedItem,
new AlertDialog.OnClickListener() {
+ @Override
public void onClick(DialogInterface dialog, int which) {
synchronized (mMethodMap) {
if (mIms == null || mIms.length <= which
@@ -1964,6 +1978,7 @@
mDialogBuilder.setPositiveButton(
com.android.internal.R.string.configure_input_methods,
new DialogInterface.OnClickListener() {
+ @Override
public void onClick(DialogInterface dialog, int whichButton) {
showConfigureInputMethods();
}
@@ -1999,6 +2014,7 @@
// ----------------------------------------------------------------------
+ @Override
public boolean setInputMethodEnabled(String id, boolean enabled) {
synchronized (mMethodMap) {
if (mContext.checkCallingOrSelfPermission(
@@ -2329,6 +2345,7 @@
/**
* @return Return the current subtype of this input method.
*/
+ @Override
public InputMethodSubtype getCurrentInputMethodSubtype() {
boolean subtypeIsSelected = false;
try {
@@ -2411,6 +2428,7 @@
}
}
+ @Override
public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
synchronized (mMethodMap) {
if (subtype != null && mCurMethodId != null) {