diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index c207738a4f887..ba15a047af4ab 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -1495,8 +1495,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @Override public void onStart() { - LocalServices.addService(InputMethodManagerInternal.class, - new LocalServiceImpl(mService)); + mService.publishLocalService(); publishBinderService(Context.INPUT_METHOD_SERVICE, mService, false /*allowIsolated*/, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO); } @@ -4866,26 +4865,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return mCurrentSubtype; } - private List getInputMethodListAsUser(@UserIdInt int userId) { - synchronized (ImfLock.class) { - return getInputMethodListLocked(userId, DirectBootAwareness.AUTO); - } - } - - private List getEnabledInputMethodListAsUser(@UserIdInt int userId) { - synchronized (ImfLock.class) { - return getEnabledInputMethodListLocked(userId); - } - } - - private void onCreateInlineSuggestionsRequest(@UserIdInt int userId, - InlineSuggestionsRequestInfo requestInfo, - IInlineSuggestionsRequestCallback callback) { - synchronized (ImfLock.class) { - onCreateInlineSuggestionsRequestLocked(userId, requestInfo, callback); - } - } - private ArrayMap queryMethodMapForUser(@UserIdInt int userId) { final ArrayMap methodMap = new ArrayMap<>(); final ArrayList methodList = new ArrayList<>(); @@ -4897,161 +4876,153 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return methodMap; } - private boolean switchToInputMethod(String imeId, @UserIdInt int userId) { - synchronized (ImfLock.class) { - if (userId == mSettings.getCurrentUserId()) { - if (!mMethodMap.containsKey(imeId) - || !mSettings.getEnabledInputMethodListLocked() - .contains(mMethodMap.get(imeId))) { - return false; // IME is not found or not enabled. - } - setInputMethodLocked(imeId, NOT_A_SUBTYPE_ID); - return true; - } - final ArrayMap methodMap = queryMethodMapForUser(userId); - final InputMethodSettings settings = new InputMethodSettings( - mContext.getResources(), mContext.getContentResolver(), methodMap, - userId, false); - if (!methodMap.containsKey(imeId) - || !settings.getEnabledInputMethodListLocked() - .contains(methodMap.get(imeId))) { + @GuardedBy("ImfLock.class") + private boolean switchToInputMethodLocked(String imeId, @UserIdInt int userId) { + if (userId == mSettings.getCurrentUserId()) { + if (!mMethodMap.containsKey(imeId) + || !mSettings.getEnabledInputMethodListLocked() + .contains(mMethodMap.get(imeId))) { return false; // IME is not found or not enabled. } - settings.putSelectedInputMethod(imeId); - settings.putSelectedSubtype(NOT_A_SUBTYPE_ID); + setInputMethodLocked(imeId, NOT_A_SUBTYPE_ID); return true; } + final ArrayMap methodMap = queryMethodMapForUser(userId); + final InputMethodSettings settings = new InputMethodSettings( + mContext.getResources(), mContext.getContentResolver(), methodMap, + userId, false); + if (!methodMap.containsKey(imeId) + || !settings.getEnabledInputMethodListLocked() + .contains(methodMap.get(imeId))) { + return false; // IME is not found or not enabled. + } + settings.putSelectedInputMethod(imeId); + settings.putSelectedSubtype(NOT_A_SUBTYPE_ID); + return true; } - private boolean setInputMethodEnabled(String imeId, boolean enabled, @UserIdInt int userId) { - synchronized (ImfLock.class) { - if (userId == mSettings.getCurrentUserId()) { - if (!mMethodMap.containsKey(imeId)) { - return false; // IME is not found. - } - setInputMethodEnabledLocked(imeId, enabled); - return true; - } - final ArrayMap methodMap = queryMethodMapForUser(userId); - final InputMethodSettings settings = new InputMethodSettings( - mContext.getResources(), mContext.getContentResolver(), methodMap, - userId, false); - if (!methodMap.containsKey(imeId)) { - return false; // IME is not found. - } - if (enabled) { - if (!settings.getEnabledInputMethodListLocked().contains(methodMap.get(imeId))) { - settings.appendAndPutEnabledInputMethodLocked(imeId, false); - } - } else { - settings.buildAndPutEnabledInputMethodsStrRemovingIdLocked( - new StringBuilder(), - settings.getEnabledInputMethodsAndSubtypeListLocked(), imeId); - } - return true; - } + private void publishLocalService() { + LocalServices.addService(InputMethodManagerInternal.class, new LocalServiceImpl()); } - private boolean transferTouchFocusToImeWindow(@NonNull IBinder sourceInputToken, - int displayId) { - //TODO(b/150843766): Check if Input Token is valid. - final IBinder curHostInputToken; - synchronized (ImfLock.class) { - if (displayId != mCurTokenDisplayId || mCurHostInputToken == null) { - return false; - } - curHostInputToken = mCurHostInputToken; - } - return mInputManagerInternal.transferTouchFocus(sourceInputToken, curHostInputToken); - } - - private void reportImeControl(@Nullable IBinder windowToken, boolean imeParentChanged) { - synchronized (ImfLock.class) { - if (mCurFocusedWindow != windowToken) { - // mCurPerceptible was set by the focused window, but it is no longer in control, - // so we reset mCurPerceptible. - mCurPerceptible = true; - } - if (imeParentChanged) { - // Hide the IME method menu earlier when the IME surface parent will change in - // case seeing the dialog dismiss flickering during the next focused window - // starting the input connection. - mMenuController.hideInputMethodMenu(); - } - } - } - - private static final class LocalServiceImpl extends InputMethodManagerInternal { - @NonNull - private final InputMethodManagerService mService; - - LocalServiceImpl(@NonNull InputMethodManagerService service) { - mService = service; - } + private final class LocalServiceImpl extends InputMethodManagerInternal { @Override public void setInteractive(boolean interactive) { // Do everything in handler so as not to block the caller. - mService.mHandler.obtainMessage(MSG_SET_INTERACTIVE, interactive ? 1 : 0, 0) - .sendToTarget(); + mHandler.obtainMessage(MSG_SET_INTERACTIVE, interactive ? 1 : 0, 0).sendToTarget(); } @Override public void hideCurrentInputMethod(@SoftInputShowHideReason int reason) { - mService.mHandler.removeMessages(MSG_HIDE_CURRENT_INPUT_METHOD); - mService.mHandler.obtainMessage(MSG_HIDE_CURRENT_INPUT_METHOD, reason).sendToTarget(); + mHandler.removeMessages(MSG_HIDE_CURRENT_INPUT_METHOD); + mHandler.obtainMessage(MSG_HIDE_CURRENT_INPUT_METHOD, reason).sendToTarget(); } @Override public List getInputMethodListAsUser(@UserIdInt int userId) { - return mService.getInputMethodListAsUser(userId); + synchronized (ImfLock.class) { + return getInputMethodListLocked(userId, DirectBootAwareness.AUTO); + } } @Override public List getEnabledInputMethodListAsUser(@UserIdInt int userId) { - return mService.getEnabledInputMethodListAsUser(userId); + synchronized (ImfLock.class) { + return getEnabledInputMethodListLocked(userId); + } } @Override public void onCreateInlineSuggestionsRequest(@UserIdInt int userId, InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback cb) { - mService.onCreateInlineSuggestionsRequest(userId, requestInfo, cb); + synchronized (ImfLock.class) { + onCreateInlineSuggestionsRequestLocked(userId, requestInfo, cb); + } } @Override public boolean switchToInputMethod(String imeId, @UserIdInt int userId) { - return mService.switchToInputMethod(imeId, userId); + synchronized (ImfLock.class) { + return switchToInputMethodLocked(imeId, userId); + } } @Override public boolean setInputMethodEnabled(String imeId, boolean enabled, @UserIdInt int userId) { - return mService.setInputMethodEnabled(imeId, enabled, userId); + synchronized (ImfLock.class) { + if (userId == mSettings.getCurrentUserId()) { + if (!mMethodMap.containsKey(imeId)) { + return false; // IME is not found. + } + setInputMethodEnabledLocked(imeId, enabled); + return true; + } + final ArrayMap methodMap = queryMethodMapForUser(userId); + final InputMethodSettings settings = new InputMethodSettings( + mContext.getResources(), mContext.getContentResolver(), methodMap, + userId, false); + if (!methodMap.containsKey(imeId)) { + return false; // IME is not found. + } + if (enabled) { + if (!settings.getEnabledInputMethodListLocked().contains( + methodMap.get(imeId))) { + settings.appendAndPutEnabledInputMethodLocked(imeId, false); + } + } else { + settings.buildAndPutEnabledInputMethodsStrRemovingIdLocked( + new StringBuilder(), + settings.getEnabledInputMethodsAndSubtypeListLocked(), imeId); + } + return true; + } } @Override public void registerInputMethodListListener(InputMethodListListener listener) { - mService.mInputMethodListListeners.addIfAbsent(listener); + mInputMethodListListeners.addIfAbsent(listener); } @Override public boolean transferTouchFocusToImeWindow(@NonNull IBinder sourceInputToken, int displayId) { - return mService.transferTouchFocusToImeWindow(sourceInputToken, displayId); + //TODO(b/150843766): Check if Input Token is valid. + final IBinder curHostInputToken; + synchronized (ImfLock.class) { + if (displayId != mCurTokenDisplayId || mCurHostInputToken == null) { + return false; + } + curHostInputToken = mCurHostInputToken; + } + return mInputManagerInternal.transferTouchFocus(sourceInputToken, curHostInputToken); } @Override public void reportImeControl(@Nullable IBinder windowToken, boolean imeParentChanged) { - mService.reportImeControl(windowToken, imeParentChanged); + synchronized (ImfLock.class) { + if (mCurFocusedWindow != windowToken) { + // mCurPerceptible was set by the focused window, but it is no longer in + // control, so we reset mCurPerceptible. + mCurPerceptible = true; + } + if (imeParentChanged) { + // Hide the IME method menu earlier when the IME surface parent will change in + // case seeing the dialog dismiss flickering during the next focused window + // starting the input connection. + mMenuController.hideInputMethodMenu(); + } + } } @Override public void removeImeSurface() { - mService.mHandler.obtainMessage(MSG_REMOVE_IME_SURFACE).sendToTarget(); + mHandler.obtainMessage(MSG_REMOVE_IME_SURFACE).sendToTarget(); } @Override public void updateImeWindowStatus(boolean disableImeIcon) { - mService.mHandler.obtainMessage(MSG_UPDATE_IME_WINDOW_STATUS, disableImeIcon ? 1 : 0, 0) + mHandler.obtainMessage(MSG_UPDATE_IME_WINDOW_STATUS, disableImeIcon ? 1 : 0, 0) .sendToTarget(); } } @@ -5689,7 +5660,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (!userHasDebugPriv(userId, shellCommand)) { continue; } - boolean failedToSelectUnknownIme = !switchToInputMethod(imeId, userId); + boolean failedToSelectUnknownIme = !switchToInputMethodLocked(imeId, userId); if (failedToSelectUnknownIme) { error.print("Unknown input method "); error.print(imeId);