summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorYohei Yukawa <yukawa@google.com>2019-01-22 19:25:44 -0800
committerYohei Yukawa <yukawa@google.com>2019-01-23 09:00:24 -0800
commitfd8f72188cb409165aa7a810d469fc471a15e207 (patch)
tree7220468c04778622a96f9b20239f75d0e9890301 /core/java/android
parentbb4e16d581abb729231cc29e60ef9a80b6429d7e (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.java42
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;
}
/**