diff options
| author | Yohei Yukawa <yukawa@google.com> | 2019-01-22 19:25:44 -0800 |
|---|---|---|
| committer | Yohei Yukawa <yukawa@google.com> | 2019-01-23 09:00:24 -0800 |
| commit | fd8f72188cb409165aa7a810d469fc471a15e207 (patch) | |
| tree | 7220468c04778622a96f9b20239f75d0e9890301 /core/java/android | |
| parent | bb4e16d581abb729231cc29e60ef9a80b6429d7e (diff) | |
Client-side reimplementation of IMM#setCurrentInputMethodSubtype()
This is a preparation to mark
InputMethodManager#setCurrentInputMethodSubtype() deprecated.
InputMethodManager#setCurrentInputMethodSubtype(), which was
introduced in Android 4.0 ICS [1], was probably mistakenly exposed as
a public API, because it has required WRITE_SECURE_SETTINGS that
typical applications cannot have.
Keeping maintaining InputMethodManager#setCurrentInputMethodSubtype()
is not that simple because now we are about to enable per-profile IME
mode, where this method needs to have a more clear spec about what
"Current" means.
An ideal solution is just removing this method, because if the caller
already has WRITE_SECURE_SETTINGS permission, they can just directly
update Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE to achieve the
same goal. However, given that this has been a public API, it would
probably make sense to provide a fallback implementation like I did
for null IME token in InputMethodManager#setInputMethod() [2].
Either way, InputMethodManager#setCurrentInputMethodSubtype() will be
marked as deprecated in a subsequent CL.
[1]: I55daa19ba924999def544bf841f00bf54852f3e1
b66d287e3003a0934d5714fbf15e554b3c814906
[2]: I42dd0325b01c527009bf85566ca8ba0766b2294e
0c1ebffdb3a459dbae549d462b97cdcdc5602816
Bug: 123249820
Test: manually done with a test app that has WRITE_SECURE_SETTINGS
Change-Id: I76da83c57cffc6b73defccfd4a1b5734c958a97e
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/view/inputmethod/InputMethodManager.java | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 14a5e3bd1417..15088d2070d2 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -27,6 +27,7 @@ import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.app.ActivityThread; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.pm.PackageManager; @@ -2492,11 +2493,48 @@ public final class InputMethodManager { */ @RequiresPermission(WRITE_SECURE_SETTINGS) public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) { + if (Process.myUid() == Process.SYSTEM_UID) { + Log.w(TAG, "System process should not call setCurrentInputMethodSubtype() because " + + "almost always it is a bug under multi-user / multi-profile environment. " + + "Consider directly interacting with InputMethodManagerService " + + "via LocalServices."); + return false; + } + if (subtype == null) { + // See the JavaDoc. This is how this method has worked. + return false; + } + final Context fallbackContext = ActivityThread.currentApplication(); + if (fallbackContext == null) { + return false; + } + if (fallbackContext.checkSelfPermission(WRITE_SECURE_SETTINGS) + != PackageManager.PERMISSION_GRANTED) { + return false; + } + final ContentResolver contentResolver = fallbackContext.getContentResolver(); + final String imeId = Settings.Secure.getString(contentResolver, + Settings.Secure.DEFAULT_INPUT_METHOD); + if (ComponentName.unflattenFromString(imeId) == null) { + // Null or invalid IME ID format. + return false; + } + final List<InputMethodSubtype> enabledSubtypes; try { - return mService.setCurrentInputMethodSubtype(subtype); + enabledSubtypes = mService.getEnabledInputMethodSubtypeList(imeId, true); } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + return false; } + final int numSubtypes = enabledSubtypes.size(); + for (int i = 0; i < numSubtypes; ++i) { + final InputMethodSubtype enabledSubtype = enabledSubtypes.get(i); + if (enabledSubtype.equals(subtype)) { + Settings.Secure.putInt(contentResolver, + Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, enabledSubtype.hashCode()); + return true; + } + } + return false; } /** |
