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 d15f68cf7cac2..e5c48f9c04358 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; @@ -111,11 +112,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; @@ -3788,6 +3791,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