diff options
| -rw-r--r-- | services/core/java/com/android/server/InputMethodManagerService.java | 100 |
1 files changed, 92 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 5b446ca11459..19170f8ff5b0 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -621,6 +621,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private final int mHardKeyboardBehavior; /** + * Whether we temporarily allow IMEs implemented in instant apps to run for testing. + * + * <p>Note: This is quite dangerous. Don't forget to reset after you finish testing.</p> + */ + private boolean mBindInstantServiceAllowed = false; + + /** * Internal state snapshot when {@link #MSG_START_INPUT} message is about to be posted to the * internal message queue. Any subsequent state change inside {@link InputMethodManagerService} * will not affect those tasks that are already posted. @@ -1068,7 +1075,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final PackageManager pm = mContext.getPackageManager(); final List<ResolveInfo> services = pm.queryIntentServicesAsUser( new Intent(InputMethod.SERVICE_INTERFACE).setPackage(packageName), - PackageManager.MATCH_DISABLED_COMPONENTS, getChangingUserId()); + getComponentMatchingFlags(PackageManager.MATCH_DISABLED_COMPONENTS), + getChangingUserId()); // No need to lock this because we access it only on getRegisteredHandler(). if (!services.isEmpty()) { mImePackageAppeared = true; @@ -1612,12 +1620,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return true; } - private boolean bindCurrentInputMethodService( + @GuardedBy("mMethodMap") + private boolean bindCurrentInputMethodServiceLocked( Intent service, ServiceConnection conn, int flags) { if (service == null || conn == null) { Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn); return false; } + if (mBindInstantServiceAllowed) { + flags |= Context.BIND_ALLOW_INSTANT; + } return mContext.bindServiceAsUser(service, conn, flags, new UserHandle(mSettings.getCurrentUserId())); } @@ -1960,7 +1972,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub com.android.internal.R.string.input_method_binding_label); mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0)); - if (bindCurrentInputMethodService(mCurIntent, this, IME_CONNECTION_BIND_FLAGS)) { + if (bindCurrentInputMethodServiceLocked(mCurIntent, this, IME_CONNECTION_BIND_FLAGS)) { mLastBindTime = SystemClock.uptimeMillis(); mHaveConnection = true; mCurId = info.getId(); @@ -2612,7 +2624,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub resultReceiver)); mInputShown = true; if (mHaveConnection && !mVisibleBound) { - bindCurrentInputMethodService( + bindCurrentInputMethodServiceLocked( mCurIntent, mVisibleConnection, IME_VISIBLE_BIND_FLAGS); mVisibleBound = true; } @@ -2627,7 +2639,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub SystemClock.uptimeMillis()-mLastBindTime,1); Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()"); mContext.unbindService(this); - bindCurrentInputMethodService(mCurIntent, this, IME_CONNECTION_BIND_FLAGS); + bindCurrentInputMethodServiceLocked(mCurIntent, this, IME_CONNECTION_BIND_FLAGS); } else { if (DEBUG) { Slog.d(TAG, "Can't show input: connection = " + mHaveConnection + ", time = " @@ -3590,6 +3602,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return false; } + @PackageManager.ResolveInfoFlags + private int getComponentMatchingFlags(@PackageManager.ResolveInfoFlags int baseFlags) { + synchronized (mMethodMap) { + if (mBindInstantServiceAllowed) { + baseFlags |= PackageManager.MATCH_INSTANT; + } + return baseFlags; + } + } + @GuardedBy("mMethodMap") void buildInputMethodListLocked(boolean resetDefaultEnabledIme) { if (DEBUG) { @@ -3613,7 +3635,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // services depending on the unlock state for the specified user. final List<ResolveInfo> services = pm.queryIntentServicesAsUser( new Intent(InputMethod.SERVICE_INTERFACE), - PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, + getComponentMatchingFlags(PackageManager.GET_META_DATA + | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS), mSettings.getCurrentUserId()); final HashMap<String, List<InputMethodSubtype>> additionalSubtypeMap = @@ -3655,7 +3678,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // conservative, but it seems we cannot use it for now (Issue 35176630). final List<ResolveInfo> allInputMethodServices = pm.queryIntentServicesAsUser( new Intent(InputMethod.SERVICE_INTERFACE), - PackageManager.MATCH_DISABLED_COMPONENTS, mSettings.getCurrentUserId()); + getComponentMatchingFlags(PackageManager.MATCH_DISABLED_COMPONENTS), + mSettings.getCurrentUserId()); final int N = allInputMethodServices.size(); for (int i = 0; i < N; ++i) { final ServiceInfo si = allInputMethodServices.get(i).serviceInfo; @@ -4598,7 +4622,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub synchronized (mMethodMap) { p.println("Current Input Method Manager state:"); int N = mMethodList.size(); - p.println(" Input Methods: mMethodMapUpdateCount=" + mMethodMapUpdateCount); + p.println(" Input Methods: mMethodMapUpdateCount=" + mMethodMapUpdateCount + + " mBindInstantServiceAllowed=" + mBindInstantServiceAllowed); for (int i=0; i<N; i++) { InputMethodInfo info = mMethodList.get(i); p.println(" InputMethod #" + i + ":"); @@ -4710,6 +4735,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if ("refresh_debug_properties".equals(cmd)) { return refreshDebugProperties(); } + if ("set-bind-instant-service-allowed".equals(cmd)) { + return setBindInstantServiceAllowed(); + } // For existing "adb shell ime <command>". if ("ime".equals(cmd)) { @@ -4740,6 +4768,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread @ShellCommandResult + private int setBindInstantServiceAllowed() { + return mService.handleSetBindInstantServiceAllowed(this); + } + + @BinderThread + @ShellCommandResult private int refreshDebugProperties() { DebugFlags.FLAG_OPTIMIZE_START_INPUT.refresh(); return ShellCommandResult.SUCCESS; @@ -4756,6 +4790,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub pw.println(" Synonym of dumpsys."); pw.println(" ime <command> [options]"); pw.println(" Manipulate IMEs. Run \"ime help\" for details."); + pw.println(" set-bind-instant-service-allowed true|false "); + pw.println(" Set whether binding to services provided by instant apps is " + + "allowed."); } } @@ -4804,6 +4841,53 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Shell command handlers: /** + * Handles {@code adb shell cmd input_method set-bind-instant-service-allowed}. + * + * @param shellCommand {@link ShellCommand} object that is handling this command. + * @return Exit code of the command. + */ + @BinderThread + @RequiresPermission(android.Manifest.permission.MANAGE_BIND_INSTANT_SERVICE) + @ShellCommandResult + private int handleSetBindInstantServiceAllowed(@NonNull ShellCommand shellCommand) { + final String allowedString = shellCommand.getNextArgRequired(); + if (allowedString == null) { + shellCommand.getErrPrintWriter().println("Error: no true/false specified"); + return ShellCommandResult.FAILURE; + } + final boolean allowed = Boolean.parseBoolean(allowedString); + synchronized (mMethodMap) { + if (mContext.checkCallingOrSelfPermission( + android.Manifest.permission.MANAGE_BIND_INSTANT_SERVICE) + != PackageManager.PERMISSION_GRANTED) { + shellCommand.getErrPrintWriter().print( + "Caller must have MANAGE_BIND_INSTANT_SERVICE permission"); + return ShellCommandResult.FAILURE; + } + + if (mBindInstantServiceAllowed == allowed) { + // Nothing to do. + return ShellCommandResult.SUCCESS; + } + mBindInstantServiceAllowed = allowed; + + // Rebuild everything. + final long ident = Binder.clearCallingIdentity(); + try { + // Reset the current IME + resetSelectedInputMethodAndSubtypeLocked(null); + // Also reset the settings of the current IME + mSettings.putSelectedInputMethod(null); + buildInputMethodListLocked(false /* resetDefaultEnabledIme */); + updateInputMethodsFromSettingsLocked(true /* enabledMayChange */); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + return ShellCommandResult.SUCCESS; + } + + /** * Handles {@code adb shell ime list}. * @param shellCommand {@link ShellCommand} object that is handling this command. * @return Exit code of the command. |