From f3417152880df95a707936644971306b23895192 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Mon, 7 Nov 2022 09:40:48 -0800 Subject: [PATCH] Plumb IME subtype change from IMMS to IMS (again) This CL introduces onInputMethodSubtypeChangedForKeyboardLayoutMapping() to InputManagerInternal in a way that is similar to our previous attempt [1]. The two major differences are A. It also provides InputMethodSubtypeHandle so that InputManagerService can use it as look up keys, and B. Subtypes that return false from isSuitableForPhysicalKeyboardLayoutMapping() [2] are mapped to null. Other than those two differences, this CL is the same as our previous CL [1]. See also another previous CL [3] about how this callback can be used. [1]: I58e71ffce9ac9131551a00dd35e24235dadfef87 b097b8262ba22040d46d6e212a31b758b7023307 [2]: Ifc0247041a43ef64f8a76a23832da2ee058c6958 6980a434cda9d1e7d9e496d91bb9a7edb41990a3 [3]: Ie88ce1ab77dbfe03ab51d89c1dc9e0a7ddbb3216 d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907 Bug: 252816846 Test: manually verified Change-Id: I087f02d06dc5575d2e657c25614d0361ef2ff443 --- .../server/input/InputManagerInternal.java | 25 +++++++++++++++++++ .../server/input/InputManagerService.java | 18 +++++++++++++ .../InputMethodManagerService.java | 17 +++++++++++++ 3 files changed, 60 insertions(+) diff --git a/services/core/java/com/android/server/input/InputManagerInternal.java b/services/core/java/com/android/server/input/InputManagerInternal.java index 62344216c3dbd..298098a572b24 100644 --- a/services/core/java/com/android/server/input/InputManagerInternal.java +++ b/services/core/java/com/android/server/input/InputManagerInternal.java @@ -17,10 +17,15 @@ package com.android.server.input; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.graphics.PointF; import android.hardware.display.DisplayViewport; import android.os.IBinder; import android.view.InputChannel; +import android.view.inputmethod.InputMethodSubtype; + +import com.android.internal.inputmethod.InputMethodSubtypeHandle; import java.util.List; @@ -135,6 +140,26 @@ public abstract class InputManagerInternal { /** Create an {@link InputChannel} that is registered to InputDispatcher. */ public abstract InputChannel createInputChannel(String inputChannelName); + /** + * Pilfer pointers from the input channel with the given token so that ongoing gestures are + * canceled for all other channels. + */ + public abstract void pilferPointers(IBinder token); + + /** + * Called when the current input method and/or {@link InputMethodSubtype} is updated. + * + * @param userId User ID to be notified about. + * @param subtypeHandle A {@link InputMethodSubtypeHandle} corresponds to {@code subtype}. + * @param subtype A {@link InputMethodSubtype} object, or {@code null} when the current + * {@link InputMethodSubtype} is not suitable for the physical keyboard layout + * mapping. + * @see InputMethodSubtype#isSuitableForPhysicalKeyboardLayoutMapping() + */ + public abstract void onInputMethodSubtypeChangedForKeyboardLayoutMapping(@UserIdInt int userId, + @Nullable InputMethodSubtypeHandle subtypeHandle, + @Nullable InputMethodSubtype subtype); + /** * Increments keyboard backlight level if the device has an associated keyboard backlight * {@see Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT} diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index d2282c3ee072e..9446d55f269b0 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -23,6 +23,7 @@ import android.Manifest; import android.annotation.EnforcePermission; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.app.ActivityManagerInternal; import android.app.Notification; import android.app.NotificationManager; @@ -110,11 +111,13 @@ import android.view.Surface; import android.view.SurfaceControl; import android.view.VerifiedInputEvent; import android.view.ViewConfiguration; +import android.view.inputmethod.InputMethodSubtype; import android.widget.Toast; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.inputmethod.InputMethodSubtypeHandle; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.os.SomeArgs; @@ -3781,6 +3784,21 @@ public class InputManagerService extends IInputManager.Stub return InputManagerService.this.createInputChannel(inputChannelName); } + @Override + public void pilferPointers(IBinder token) { + mNative.pilferPointers(token); + } + + @Override + public void onInputMethodSubtypeChangedForKeyboardLayoutMapping(@UserIdInt int userId, + @Nullable InputMethodSubtypeHandle subtypeHandle, + @Nullable InputMethodSubtype subtype) { + if (DEBUG) { + Slog.i(TAG, "InputMethodSubtype changed: userId=" + userId + + " subtypeHandle=" + subtypeHandle); + } + } + @Override public void incrementKeyboardBacklight(int deviceId) { mKeyboardBacklightController.incrementKeyboardBacklight(deviceId); diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 4d1c5aede33df..114c512b3f95b 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -162,6 +162,7 @@ import com.android.internal.inputmethod.InlineSuggestionsRequestInfo; import com.android.internal.inputmethod.InputBindResult; import com.android.internal.inputmethod.InputMethodDebug; import com.android.internal.inputmethod.InputMethodNavButtonFlags; +import com.android.internal.inputmethod.InputMethodSubtypeHandle; import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.inputmethod.StartInputFlags; import com.android.internal.inputmethod.StartInputReason; @@ -3200,6 +3201,18 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub sendOnNavButtonFlagsChangedLocked(); } + @GuardedBy("ImfLock.class") + private void notifyInputMethodSubtypeChangedLocked(@UserIdInt int userId, + @NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { + final InputMethodSubtype normalizedSubtype = + subtype != null && subtype.isSuitableForPhysicalKeyboardLayoutMapping() + ? subtype : null; + final InputMethodSubtypeHandle newSubtypeHandle = normalizedSubtype != null + ? InputMethodSubtypeHandle.of(imi, normalizedSubtype) : null; + mInputManagerInternal.onInputMethodSubtypeChangedForKeyboardLayoutMapping( + userId, newSubtypeHandle, normalizedSubtype); + } + @GuardedBy("ImfLock.class") void setInputMethodLocked(String id, int subtypeId) { InputMethodInfo info = mMethodMap.get(id); @@ -3209,8 +3222,10 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // See if we need to notify a subtype change within the same IME. if (id.equals(getSelectedMethodIdLocked())) { + final int userId = mSettings.getCurrentUserId(); final int subtypeCount = info.getSubtypeCount(); if (subtypeCount <= 0) { + notifyInputMethodSubtypeChangedLocked(userId, info, null); return; } final InputMethodSubtype oldSubtype = mCurrentSubtype; @@ -3225,6 +3240,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (newSubtype == null || oldSubtype == null) { Slog.w(TAG, "Illegal subtype state: old subtype = " + oldSubtype + ", new subtype = " + newSubtype); + notifyInputMethodSubtypeChangedLocked(userId, info, null); return; } if (newSubtype != oldSubtype) { @@ -5297,6 +5313,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mCurrentSubtype = getCurrentInputMethodSubtypeLocked(); } } + notifyInputMethodSubtypeChangedLocked(mSettings.getCurrentUserId(), imi, mCurrentSubtype); if (!setSubtypeOnly) { // Set InputMethod here