From ea675ead0a999aac1db265cd9649f1a4afa427c0 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Mon, 18 Jul 2022 22:31:40 -0700 Subject: [PATCH] Implement IMM#showInputMethodAndSubtypeEnabler() in the client side With this CL, InputMethodManager#showInputMethodAndSubtypeEnabler() is fully implemented in the client side. By not using system_server privileged context to launch the Settings activity, we can stop worrying about conflicts with existing security concepts such as * Background Activity launch blocking mechanism * Restrictions for instant apps Bug: 34886274 Test: Manually verified as follows. 1. Build aosp_coral-userdebug and flash it. 2. adb install -r $ANDROID_TARGET_OUT_TESTCASES/ApiDemos/arm64/ApiDemos.apk 3. adb shell am start -n com.example.android.apis/.ApiDemos 4. View -> Input Method -> ShowInputMethodAndSubtypeEnabler 5. Verify that the API works. Change-Id: I5199ca4609c03900a0e86011d344b054b1df08dd --- .../IInputMethodManagerInvoker.java | 10 ------- .../view/inputmethod/InputMethodManager.java | 24 ++++++++++++++- .../internal/view/IInputMethodManager.aidl | 3 -- .../InputMethodManagerService.java | 29 ------------------- 4 files changed, 23 insertions(+), 43 deletions(-) diff --git a/core/java/android/view/inputmethod/IInputMethodManagerInvoker.java b/core/java/android/view/inputmethod/IInputMethodManagerInvoker.java index 489e70242a950..46ca79d6ff37e 100644 --- a/core/java/android/view/inputmethod/IInputMethodManagerInvoker.java +++ b/core/java/android/view/inputmethod/IInputMethodManagerInvoker.java @@ -179,16 +179,6 @@ final class IInputMethodManagerInvoker { } } - @AnyThread - void showInputMethodAndSubtypeEnablerFromClient(@NonNull IInputMethodClient client, - @Nullable String imeId) { - try { - mTarget.showInputMethodAndSubtypeEnablerFromClient(client, imeId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - @AnyThread boolean isInputMethodPickerShownForTest() { try { diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 52947a54e167a..a75e92d96f507 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -53,9 +53,11 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Matrix; import android.graphics.Rect; +import android.hardware.display.DisplayManager; import android.inputmethodservice.InputMethodService; import android.os.Binder; import android.os.Build; @@ -71,6 +73,7 @@ import android.os.ServiceManager.ServiceNotFoundException; import android.os.Trace; import android.os.UserHandle; import android.provider.Settings; +import android.text.TextUtils; import android.text.style.SuggestionSpan; import android.util.Log; import android.util.Pools.Pool; @@ -3243,7 +3246,26 @@ public final class InputMethodManager { * subtypes of all input methods will be shown. */ public void showInputMethodAndSubtypeEnabler(@Nullable String imiId) { - mServiceInvoker.showInputMethodAndSubtypeEnablerFromClient(mClient, imiId); + Context context = null; + synchronized (mH) { + if (mCurRootView != null) { + context = mCurRootView.mContext; + } + } + if (context == null) { + final Context appContext = ActivityThread.currentApplication(); + final DisplayManager displayManager = appContext.getSystemService(DisplayManager.class); + context = appContext.createDisplayContext(displayManager.getDisplay(mDisplayId)); + } + + final Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED + | Intent.FLAG_ACTIVITY_CLEAR_TOP); + if (!TextUtils.isEmpty(imiId)) { + intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, imiId); + } + context.startActivity(intent); } /** diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 95cb729b3f7fa..2c56842d8ee21 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -82,9 +82,6 @@ interface IInputMethodManager { void showInputMethodPickerFromSystem(in IInputMethodClient client, int auxiliarySubtypeMode, int displayId); - void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, - @nullable String topId); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = " + "android.Manifest.permission.TEST_INPUT_METHOD)") boolean isInputMethodPickerShownForTest(); diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 8cd35d506c975..b373a30792a15 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -4051,18 +4051,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } } - @Override - public void showInputMethodAndSubtypeEnablerFromClient( - IInputMethodClient client, String inputMethodId) { - synchronized (ImfLock.class) { - // TODO(yukawa): Should we verify the display ID? - if (!calledFromValidUserLocked()) { - return; - } - showInputMethodAndSubtypeEnabler(inputMethodId); - } - } - @BinderThread private boolean switchToPreviousInputMethod(@NonNull IBinder token) { synchronized (ImfLock.class) { @@ -5219,23 +5207,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // ---------------------------------------------------------------------- - private void showInputMethodAndSubtypeEnabler(String inputMethodId) { - Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED - | Intent.FLAG_ACTIVITY_CLEAR_TOP); - if (!TextUtils.isEmpty(inputMethodId)) { - intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, inputMethodId); - } - final int userId; - synchronized (ImfLock.class) { - userId = mSettings.getCurrentUserId(); - } - mContext.startActivityAsUser(intent, null, UserHandle.of(userId)); - } - - // ---------------------------------------------------------------------- - /** * Enable or disable the given IME by updating {@link Settings.Secure#ENABLED_INPUT_METHODS}. *