From 9f24351f4affb52bdc94fe865d851d0ab6f5a260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cosmin=20B=C4=83ie=C8=99?= Date: Mon, 6 Mar 2023 12:35:49 +0100 Subject: [PATCH] Cleanup IME window visibility flag logic Cache last reported imeWindowVisibility value in IME to avoid sending duplicate IPC calls Remove updates to imeWindowVisibility that were not needed Handle imeWindowVisibility updates when a service disconnects (e.g. when the currently shown IME is being updated/uninstalled) Test: observe navigation bar behaviour when showing/hiding IME in different apps, when rotating the screen with IME shown, when in split screen, when switching between IMEs, and when updating/uninstalling the IME that is currently visible Bug: 271816203 Change-Id: I7980a68bca22009c364a635e557214da2ccf7fa9 --- .../InputMethodService.java | 82 ++++++++++-------- .../InputMethodPrivilegedOperations.java | 9 +- .../statusbar/RegisterStatusBarResult.java | 13 ++- .../shared/recents/utilities/Utilities.java | 3 +- .../systemui/navigationbar/NavBarHelper.java | 2 +- .../systemui/navigationbar/NavigationBar.java | 6 +- .../navigationbar/TaskbarDelegate.java | 5 +- .../systemui/statusbar/CommandQueue.java | 19 +++-- .../com/android/systemui/wmshell/WMShell.java | 6 +- .../navigationbar/NavigationBarTest.java | 3 +- .../systemui/statusbar/CommandQueueTest.java | 3 +- .../InputMethodBindingController.java | 1 + .../InputMethodManagerService.java | 85 ++++++++++--------- .../statusbar/StatusBarManagerInternal.java | 9 +- .../statusbar/StatusBarManagerService.java | 18 ++-- 15 files changed, 153 insertions(+), 111 deletions(-) diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index a9c4818393a8f..2f9c2073cd384 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -52,8 +52,6 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.WindowInsets.Type.navigationBars; import static android.view.WindowInsets.Type.statusBars; -import static java.lang.annotation.RetentionPolicy.SOURCE; - import android.annotation.AnyThread; import android.annotation.CallSuper; import android.annotation.DrawableRes; @@ -160,6 +158,7 @@ import com.android.internal.inputmethod.InputMethodNavButtonFlags; import com.android.internal.inputmethod.InputMethodPrivilegedOperations; import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry; import com.android.internal.inputmethod.SoftInputShowHideReason; +import com.android.internal.util.Preconditions; import com.android.internal.util.RingBuffer; import org.xmlpull.v1.XmlPullParserException; @@ -482,43 +481,53 @@ public class InputMethodService extends AbstractInputMethodService { public static final int BACK_DISPOSITION_ADJUST_NOTHING = 3; /** - * Enum flag to be used for {@link #setBackDisposition(int)}. + * Enum values to be used for {@link #setBackDisposition(int)}. * * @hide */ - @Retention(SOURCE) - @IntDef(value = {BACK_DISPOSITION_DEFAULT, BACK_DISPOSITION_WILL_NOT_DISMISS, - BACK_DISPOSITION_WILL_DISMISS, BACK_DISPOSITION_ADJUST_NOTHING}, - prefix = "BACK_DISPOSITION_") + @IntDef(prefix = { "BACK_DISPOSITION_" }, value = { + BACK_DISPOSITION_DEFAULT, + BACK_DISPOSITION_WILL_NOT_DISMISS, + BACK_DISPOSITION_WILL_DISMISS, + BACK_DISPOSITION_ADJUST_NOTHING, + }) + @Retention(RetentionPolicy.SOURCE) public @interface BackDispositionMode {} /** + * Enum flags to be used for {@link #setImeWindowStatus}, representing the current state of the + * IME window visibility. + * * @hide + */ + @IntDef(flag = true, prefix = { "IME_" }, value = { + IME_ACTIVE, + IME_VISIBLE, + IME_VISIBLE_IMPERCEPTIBLE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ImeWindowVisibility {} + + /** * The IME is active. It may or may not be visible. + * @hide */ public static final int IME_ACTIVE = 0x1; /** - * @hide * The IME is perceptibly visible to the user. + * @hide */ public static final int IME_VISIBLE = 0x2; /** - * @hide - * The IME is active and ready with views but set invisible. - * This flag cannot be combined with {@link #IME_VISIBLE}. - */ - public static final int IME_INVISIBLE = 0x4; - - /** - * @hide * The IME is visible, but not yet perceptible to the user (e.g. fading in) * by {@link android.view.WindowInsetsController}. * * @see InputMethodManager#reportPerceptible + * @hide */ - public static final int IME_VISIBLE_IMPERCEPTIBLE = 0x8; + public static final int IME_VISIBLE_IMPERCEPTIBLE = 0x4; // Min and max values for back disposition. private static final int BACK_DISPOSITION_MIN = BACK_DISPOSITION_DEFAULT; @@ -631,9 +640,18 @@ public class InputMethodService extends AbstractInputMethodService { int mStatusIcon; + /** + * Latest value reported of back disposition mode. + */ @BackDispositionMode int mBackDisposition; + /** + * Latest value reported of IME window visibility flags. + */ + @ImeWindowVisibility + private int mImeWindowVisibility; + private Object mLock = new Object(); @GuardedBy("mLock") private boolean mNotifyUserActionSent; @@ -1210,8 +1228,14 @@ public class InputMethodService extends AbstractInputMethodService { mImeSurfaceRemoverRunnable = null; } - private void setImeWindowStatus(int visibilityFlags, int backDisposition) { - mPrivOps.setImeWindowStatusAsync(visibilityFlags, backDisposition); + private void setImeWindowStatus(@ImeWindowVisibility int vis, + @BackDispositionMode int backDisposition) { + if (vis == mImeWindowVisibility && backDisposition == mBackDisposition) { + return; + } + mImeWindowVisibility = Preconditions.checkFlagsArgument(vis, IME_ACTIVE | IME_VISIBLE); + mBackDisposition = backDisposition; + mPrivOps.setImeWindowStatusAsync(mImeWindowVisibility, mBackDisposition); } /** Set region of the keyboard to be avoided from back gesture */ @@ -1885,15 +1909,11 @@ public class InputMethodService extends AbstractInputMethodService { * @param disposition disposition mode to be set */ public void setBackDisposition(@BackDispositionMode int disposition) { - if (disposition == mBackDisposition) { - return; - } - if (disposition > BACK_DISPOSITION_MAX || disposition < BACK_DISPOSITION_MIN) { + if (disposition < BACK_DISPOSITION_MIN || disposition > BACK_DISPOSITION_MAX) { Log.e(TAG, "Invalid back disposition value (" + disposition + ") specified."); return; } - mBackDisposition = disposition; - setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition); + setImeWindowStatus(mImeWindowVisibility, disposition); } /** @@ -2867,14 +2887,8 @@ public class InputMethodService extends AbstractInputMethodService { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.showWindow"); mDecorViewWasVisible = mDecorViewVisible; mInShowWindow = true; - final int previousImeWindowStatus = - (mDecorViewVisible ? IME_ACTIVE : 0) | (isInputViewShown() - ? (!mWindowVisible ? IME_INVISIBLE : IME_VISIBLE) : 0); startViews(prepareWindow(showInput)); - final int nextImeWindowStatus = mapToImeWindowStatus(); - if (previousImeWindowStatus != nextImeWindowStatus) { - setImeWindowStatus(nextImeWindowStatus, mBackDisposition); - } + setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition); mNavigationBarController.onWindowShown(); // compute visibility @@ -4085,9 +4099,9 @@ public class InputMethodService extends AbstractInputMethodService { }; } + @ImeWindowVisibility private int mapToImeWindowStatus() { - return IME_ACTIVE - | (isInputViewShown() ? IME_VISIBLE : 0); + return IME_ACTIVE | (mDecorViewVisible ? IME_VISIBLE : 0); } private boolean isAutomotive() { diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java index 66e3333acf7c1..1a38049006659 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java +++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java @@ -20,6 +20,7 @@ import android.annotation.AnyThread; import android.annotation.DrawableRes; import android.annotation.NonNull; import android.annotation.Nullable; +import android.inputmethodservice.InputMethodService; import android.net.Uri; import android.os.IBinder; import android.os.RemoteException; @@ -105,14 +106,10 @@ public final class InputMethodPrivilegedOperations { * * @param vis visibility flags * @param backDisposition disposition flags - * @see android.inputmethodservice.InputMethodService#IME_ACTIVE - * @see android.inputmethodservice.InputMethodService#IME_VISIBLE - * @see android.inputmethodservice.InputMethodService#IME_INVISIBLE - * @see android.inputmethodservice.InputMethodService#BACK_DISPOSITION_DEFAULT - * @see android.inputmethodservice.InputMethodService#BACK_DISPOSITION_ADJUST_NOTHING */ @AnyThread - public void setImeWindowStatusAsync(int vis, int backDisposition) { + public void setImeWindowStatusAsync(@InputMethodService.ImeWindowVisibility int vis, + @InputMethodService.BackDispositionMode int backDisposition) { final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull(); if (ops == null) { return; diff --git a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java index 4f827cda6afaf..8b9a9913183d5 100644 --- a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java +++ b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java @@ -16,6 +16,7 @@ package com.android.internal.statusbar; +import android.inputmethodservice.InputMethodService; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; @@ -31,7 +32,9 @@ public final class RegisterStatusBarResult implements Parcelable { public final int mDisabledFlags1; // switch[0] public final int mAppearance; // switch[1] public final AppearanceRegion[] mAppearanceRegions; // switch[2] + @InputMethodService.ImeWindowVisibility public final int mImeWindowVis; // switch[3] + @InputMethodService.BackDispositionMode public final int mImeBackDisposition; // switch[4] public final boolean mShowImeSwitcher; // switch[5] public final int mDisabledFlags2; // switch[6] @@ -44,10 +47,12 @@ public final class RegisterStatusBarResult implements Parcelable { public final LetterboxDetails[] mLetterboxDetails; public RegisterStatusBarResult(ArrayMap icons, int disabledFlags1, - int appearance, AppearanceRegion[] appearanceRegions, int imeWindowVis, - int imeBackDisposition, boolean showImeSwitcher, int disabledFlags2, IBinder imeToken, - boolean navbarColorManagedByIme, int behavior, int requestedVisibleTypes, - String packageName, int transientBarTypes, LetterboxDetails[] letterboxDetails) { + int appearance, AppearanceRegion[] appearanceRegions, + @InputMethodService.ImeWindowVisibility int imeWindowVis, + @InputMethodService.BackDispositionMode int imeBackDisposition, boolean showImeSwitcher, + int disabledFlags2, IBinder imeToken, boolean navbarColorManagedByIme, int behavior, + int requestedVisibleTypes, String packageName, int transientBarTypes, + LetterboxDetails[] letterboxDetails) { mIcons = new ArrayMap<>(icons); mDisabledFlags1 = disabledFlags1; mAppearance = appearance; diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java index 751a3f8458bd7..2e6c485336f32 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java @@ -104,7 +104,8 @@ public class Utilities { * @return updated set of flags from InputMethodService based off {@param oldHints} * Leaves original hints unmodified */ - public static int calculateBackDispositionHints(int oldHints, int backDisposition, + public static int calculateBackDispositionHints(int oldHints, + @InputMethodService.BackDispositionMode int backDisposition, boolean imeShown, boolean showImeSwitcher) { int hints = oldHints; switch (backDisposition) { diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java index 8225c47d904b2..99c591f25edbb 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java @@ -462,7 +462,7 @@ public final class NavBarHelper implements * @return Whether the IME is shown on top of the screen given the {@code vis} flag of * {@link InputMethodService} and the keyguard states. */ - public boolean isImeShown(int vis) { + public boolean isImeShown(@InputMethodService.ImeWindowVisibility int vis) { View shadeWindowView = mNotificationShadeWindowController.getWindowRootView(); boolean isKeyguardShowing = mKeyguardStateController.isShowing(); boolean imeVisibleOnShade = shadeWindowView != null && shadeWindowView.isAttachedToWindow() diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 682335e0b419a..5bae1cba4ac4b 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -66,6 +66,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; +import android.inputmethodservice.InputMethodService; import android.os.Binder; import android.os.Bundle; import android.os.Handler; @@ -1047,8 +1048,9 @@ public class NavigationBar extends ViewController implements // ----- CommandQueue Callbacks ----- @Override - public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, - boolean showImeSwitcher) { + public void setImeWindowStatus(int displayId, IBinder token, + @InputMethodService.ImeWindowVisibility int vis, + @InputMethodService.BackDispositionMode int backDisposition, boolean showImeSwitcher) { if (displayId != mDisplayId) { return; } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index b96ca7ac29617..e6fab1b1eb44b 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -339,8 +339,9 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, } @Override - public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, - boolean showImeSwitcher) { + public void setImeWindowStatus(int displayId, IBinder token, + @InputMethodService.ImeWindowVisibility int vis, + @InputMethodService.BackDispositionMode int backDisposition, boolean showImeSwitcher) { boolean imeShown = mNavBarHelper.isImeShown(vis); if (!imeShown) { // Count imperceptible changes as visible so we transition taskbar out quickly. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index a532195c5b9f3..6c2c0cf12aadf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -19,7 +19,6 @@ package com.android.systemui.statusbar; import static android.app.StatusBarManager.DISABLE2_NONE; import static android.app.StatusBarManager.DISABLE_NONE; import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT; -import static android.inputmethodservice.InputMethodService.IME_INVISIBLE; import static android.view.Display.INVALID_DISPLAY; import android.annotation.Nullable; @@ -37,7 +36,7 @@ import android.hardware.biometrics.IBiometricContextListener; import android.hardware.biometrics.IBiometricSysuiReceiver; import android.hardware.biometrics.PromptInfo; import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback; -import android.inputmethodservice.InputMethodService.BackDispositionMode; +import android.inputmethodservice.InputMethodService; import android.media.INearbyMediaDevicesProvider; import android.media.MediaRoute2Info; import android.os.Binder; @@ -226,8 +225,10 @@ public class CommandQueue extends IStatusBar.Stub implements * @param backDisposition Disposition mode of back button. It should be one of below flags: * @param showImeSwitcher {@code true} to show IME switch button. */ - default void setImeWindowStatus(int displayId, IBinder token, int vis, - @BackDispositionMode int backDisposition, boolean showImeSwitcher) { } + default void setImeWindowStatus(int displayId, IBinder token, + @InputMethodService.ImeWindowVisibility int vis, + @InputMethodService.BackDispositionMode int backDisposition, + boolean showImeSwitcher) { } default void showRecentApps(boolean triggeredFromAltTab) { } default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { } default void toggleTaskbar() { } @@ -678,7 +679,9 @@ public class CommandQueue extends IStatusBar.Stub implements } @Override - public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, + public void setImeWindowStatus(int displayId, IBinder token, + @InputMethodService.ImeWindowVisibility int vis, + @InputMethodService.BackDispositionMode int backDisposition, boolean showImeSwitcher) { synchronized (mLock) { mHandler.removeMessages(MSG_SHOW_IME_BUTTON); @@ -1092,7 +1095,9 @@ public class CommandQueue extends IStatusBar.Stub implements } } - private void handleShowImeButton(int displayId, IBinder token, int vis, int backDisposition, + private void handleShowImeButton(int displayId, IBinder token, + @InputMethodService.ImeWindowVisibility int vis, + @InputMethodService.BackDispositionMode int backDisposition, boolean showImeSwitcher) { if (displayId == INVALID_DISPLAY) return; @@ -1112,7 +1117,7 @@ public class CommandQueue extends IStatusBar.Stub implements private void sendImeInvisibleStatusForPrevNavBar() { for (int i = 0; i < mCallbacks.size(); i++) { mCallbacks.get(i).setImeWindowStatus(mLastUpdatedImeDisplayId, - null /* token */, IME_INVISIBLE, BACK_DISPOSITION_DEFAULT, + null /* token */, 0 /* vis */, BACK_DISPOSITION_DEFAULT, false /* showImeSwitcher */); } } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index 5144d19662227..4c7e6b007f38c 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -334,8 +334,10 @@ public final class WMShell implements } @Override - public void setImeWindowStatus(int displayId, IBinder token, int vis, - int backDisposition, boolean showImeSwitcher) { + public void setImeWindowStatus(int displayId, IBinder token, + @InputMethodService.ImeWindowVisibility int vis, + @InputMethodService.BackDispositionMode int backDisposition, + boolean showImeSwitcher) { if (displayId == mDisplayTracker.getDefaultDisplayId() && (vis & InputMethodService.IME_VISIBLE) != 0) { oneHanded.stopOneHanded( diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java index 25d494cee5e87..697d1a3b775c9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -20,7 +20,6 @@ import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT; import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN; import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT; -import static android.inputmethodservice.InputMethodService.IME_INVISIBLE; import static android.inputmethodservice.InputMethodService.IME_VISIBLE; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS; @@ -364,7 +363,7 @@ public class NavigationBarTest extends SysuiTestCase { externalNavBar.setImeWindowStatus(EXTERNAL_DISPLAY_ID, null, IME_VISIBLE, BACK_DISPOSITION_DEFAULT, true); defaultNavBar.setImeWindowStatus( - DEFAULT_DISPLAY, null, IME_INVISIBLE, BACK_DISPOSITION_DEFAULT, false); + DEFAULT_DISPLAY, null, 0 /* vis */, BACK_DISPOSITION_DEFAULT, false); // Verify IME window state will be updated in external NavBar & default NavBar state reset. assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN | NAVIGATION_HINT_IME_SWITCHER_SHOWN, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java index 1643e174ee134..385d556092a65 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java @@ -16,7 +16,6 @@ package com.android.systemui.statusbar; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT; -import static android.inputmethodservice.InputMethodService.IME_INVISIBLE; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT; @@ -201,7 +200,7 @@ public class CommandQueueTest extends SysuiTestCase { mCommandQueue.setImeWindowStatus(SECONDARY_DISPLAY, null, 1, 2, true); waitForIdleSync(); - verify(mCallbacks).setImeWindowStatus(eq(DEFAULT_DISPLAY), eq(null), eq(IME_INVISIBLE), + verify(mCallbacks).setImeWindowStatus(eq(DEFAULT_DISPLAY), eq(null), eq(0), eq(BACK_DISPOSITION_DEFAULT), eq(false)); verify(mCallbacks).setImeWindowStatus( eq(SECONDARY_DISPLAY), eq(null), eq(1), eq(2), eq(true)); diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java index ba9e280be49d0..b0b1d676bc4b8 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java @@ -352,6 +352,7 @@ final class InputMethodBindingController { clearCurMethodAndSessions(); mService.clearInputShownLocked(); mService.unbindCurrentClientLocked(UnbindReason.DISCONNECT_IME); + mService.resetSystemUiLocked(); } } } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 57f8d1478905c..8c137e2eb44c4 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -633,8 +633,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub private InputMethodSubtype mCurrentSubtype; /** - * {@code true} if the IME has not been mostly hidden via {@link android.view.InsetsController} + * {@code true} if the IME has not been mostly hidden via {@link android.view.InsetsController}. */ + @GuardedBy("ImfLock.class") private boolean mCurPerceptible; /** @@ -748,33 +749,26 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub SparseArray mEnabledAccessibilitySessions = new SparseArray<>(); /** - * True if the device is currently interactive with user. The value is true initially. + * {@code true} if the device is currently interactive with the user, initially true. + * + * @see #handleSetInteractive */ + @GuardedBy("ImfLock.class") boolean mIsInteractive = true; + @GuardedBy("ImfLock.class") + @InputMethodService.BackDispositionMode int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT; /** - * A set of status bits regarding the active IME. + * The {@link InputMethodService.ImeWindowVisibility} of the currently bound IME, + * or {@code 0} if no IME is bound. * - *

This value is a combination of following two bits:

- *
- *
{@link InputMethodService#IME_ACTIVE}
- *
- * If this bit is ON, connected IME is ready to accept touch/key events. - *
- *
{@link InputMethodService#IME_VISIBLE}
- *
- * If this bit is ON, some of IME view, e.g. software input, candidate view, is visible. - *
- *
{@link InputMethodService#IME_INVISIBLE}
- *
If this bit is ON, IME is ready with views from last EditorInfo but is - * currently invisible. - *
- *
- * Do not update this value outside of {@link #setImeWindowStatus(IBinder, int, int)} and + *

Do not update this value outside of {@link #setImeWindowStatus(IBinder, int, int)} and * {@link InputMethodBindingController#unbindCurrentMethod()}. */ + @GuardedBy("ImfLock.class") + @InputMethodService.ImeWindowVisibility int mImeWindowVis; private LocaleList mLastSystemLocales; @@ -1535,7 +1529,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // Uh oh, current input method is no longer around! // Pick another one... Slog.i(TAG, "Current input method removed: " + curInputMethodId); - updateSystemUiLocked(0 /* vis */, mBackDisposition); if (!chooseNewDefaultIMELocked()) { changed = true; curIm = null; @@ -2938,7 +2931,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub sessionState.mSession.finishSession(); } catch (RemoteException e) { Slog.w(TAG, "Session failed to close due to remote exception", e); - updateSystemUiLocked(0 /* vis */, mBackDisposition); } sessionState.mSession = null; } @@ -3048,15 +3040,15 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } @GuardedBy("ImfLock.class") - private boolean shouldShowImeSwitcherLocked(int visibility) { + private boolean shouldShowImeSwitcherLocked( + @InputMethodService.ImeWindowVisibility int visibility) { if (!mShowOngoingImeSwitcherForPhones) return false; if (mMenuController.getSwitchingDialogLocked() != null) return false; if (mWindowManagerInternal.isKeyguardShowingAndNotOccluded() && mWindowManagerInternal.isKeyguardSecure(mSettings.getCurrentUserId())) { return false; } - if ((visibility & InputMethodService.IME_ACTIVE) == 0 - || (visibility & InputMethodService.IME_INVISIBLE) != 0) { + if ((visibility & InputMethodService.IME_ACTIVE) == 0) { return false; } if (mWindowManagerInternal.isHardKeyboardAvailable()) { @@ -3115,7 +3107,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread @SuppressWarnings("deprecation") - private void setImeWindowStatus(@NonNull IBinder token, int vis, int backDisposition) { + private void setImeWindowStatus(@NonNull IBinder token, + @InputMethodService.ImeWindowVisibility int vis, + @InputMethodService.BackDispositionMode int backDisposition) { final int topFocusedDisplayId = mWindowManagerInternal.getTopFocusedDisplayId(); synchronized (ImfLock.class) { @@ -3132,7 +3126,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } mImeWindowVis = vis; mBackDisposition = backDisposition; - updateSystemUiLocked(vis, backDisposition); + updateSystemUiLocked(mImeWindowVis, mBackDisposition); } final boolean dismissImeOnBackKeyPressed; @@ -3167,37 +3161,46 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub private void updateImeWindowStatus(boolean disableImeIcon) { synchronized (ImfLock.class) { - if (disableImeIcon) { - updateSystemUiLocked(0, mBackDisposition); - } else { - updateSystemUiLocked(); - } + // TODO(b/285109020): disableImeIcon should be stored in a property like + // mIsSwitcherIconDisabled, but it is currently not reliably cleared. + updateSystemUiLocked(disableImeIcon ? 0 : mImeWindowVis, mBackDisposition); } } @GuardedBy("ImfLock.class") void updateSystemUiLocked() { + // This is only used by InputMethodMenuController to trigger the IME switcher icon + // visibility, by having {@code shouldShowImeSwitcherLocked} called, which depends on the + // visibility of the IME switcher dialog. updateSystemUiLocked(mImeWindowVis, mBackDisposition); } // Caution! This method is called in this class. Handle multi-user carefully @GuardedBy("ImfLock.class") - private void updateSystemUiLocked(int vis, int backDisposition) { + private void updateSystemUiLocked(@InputMethodService.ImeWindowVisibility int vis, + @InputMethodService.BackDispositionMode int backDisposition) { if (getCurTokenLocked() == null) { return; } if (DEBUG) { Slog.d(TAG, "IME window vis: " + vis - + " active: " + (vis & InputMethodService.IME_ACTIVE) - + " inv: " + (vis & InputMethodService.IME_INVISIBLE) + + " active: " + ((vis & InputMethodService.IME_ACTIVE) != 0) + + " visible: " + ((vis & InputMethodService.IME_VISIBLE) != 0) + + " backDisposition: " + backDisposition + + " isInteractive: " + mIsInteractive + + " curPerceptible: " + mCurPerceptible + " displayId: " + mCurTokenDisplayId); } // TODO: Move this clearing calling identity block to setImeWindowStatus after making sure - // all updateSystemUi happens on system privilege. + // all updateSystemUi happens on system privilege. final long ident = Binder.clearCallingIdentity(); try { - if (!mCurPerceptible) { + if (!mIsInteractive) { + // When we are not interactive, + // the visibility should be 0 (no IME icons should be shown). + vis = 0; + } else if (!mCurPerceptible) { if ((vis & InputMethodService.IME_VISIBLE) != 0) { vis &= ~InputMethodService.IME_VISIBLE; vis |= InputMethodService.IME_VISIBLE_IMPERCEPTIBLE; @@ -3527,7 +3530,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return; } mCurPerceptible = perceptible; - updateSystemUiLocked(); + updateSystemUiLocked(mImeWindowVis, mBackDisposition); } }); } @@ -5089,8 +5092,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub private void handleSetInteractive(final boolean interactive) { synchronized (ImfLock.class) { + if (mIsInteractive == interactive) { + return; + } mIsInteractive = interactive; - updateSystemUiLocked(interactive ? mImeWindowVis : 0, mBackDisposition); + updateSystemUiLocked(mImeWindowVis, mBackDisposition); // Inform the current client of the change in active status if (mCurClient == null || mCurClient.mClient == null) { @@ -6725,7 +6731,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread @Override - public void setImeWindowStatusAsync(int vis, int backDisposition) { + public void setImeWindowStatusAsync(@InputMethodService.ImeWindowVisibility int vis, + @InputMethodService.BackDispositionMode int backDisposition) { mImms.setImeWindowStatus(mToken, vis, backDisposition); } diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java index efd8b6d9a9432..6e9a22c7872b2 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java @@ -19,6 +19,7 @@ package com.android.server.statusbar; import android.annotation.Nullable; import android.app.ITransientNotificationCallback; import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback; +import android.inputmethodservice.InputMethodService; import android.os.Bundle; import android.os.IBinder; import android.view.WindowInsets.Type.InsetsType; @@ -54,13 +55,13 @@ public interface StatusBarManagerInternal { * @param displayId The display to which the IME is bound to. * @param token The IME token. * @param vis Bit flags about the IME visibility. - * (e.g. {@link android.inputmethodservice.InputMethodService#IME_ACTIVE}) * @param backDisposition Bit flags about the IME back disposition. - * (e.g. {@link android.inputmethodservice.InputMethodService#BACK_DISPOSITION_DEFAULT}) * @param showImeSwitcher {@code true} when the IME switcher button should be shown. */ - void setImeWindowStatus(int displayId, IBinder token, int vis, - int backDisposition, boolean showImeSwitcher); + void setImeWindowStatus(int displayId, IBinder token, + @InputMethodService.ImeWindowVisibility int vis, + @InputMethodService.BackDispositionMode int backDisposition, + boolean showImeSwitcher); /** * See {@link android.app.StatusBarManager#setIcon(String, int, int, String)}. diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 044d30b368dab..719b2d2f03553 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -59,6 +59,7 @@ import android.hardware.biometrics.PromptInfo; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback; +import android.inputmethodservice.InputMethodService; import android.media.INearbyMediaDevicesProvider; import android.media.MediaRoute2Info; import android.net.Uri; @@ -516,7 +517,9 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, + public void setImeWindowStatus(int displayId, IBinder token, + @InputMethodService.ImeWindowVisibility int vis, + @InputMethodService.BackDispositionMode int backDisposition, boolean showImeSwitcher) { StatusBarManagerService.this.setImeWindowStatus(displayId, token, vis, backDisposition, showImeSwitcher); @@ -1221,12 +1224,14 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public void setImeWindowStatus(int displayId, final IBinder token, final int vis, - final int backDisposition, final boolean showImeSwitcher) { + public void setImeWindowStatus(int displayId, final IBinder token, + @InputMethodService.ImeWindowVisibility final int vis, + @InputMethodService.BackDispositionMode final int backDisposition, + final boolean showImeSwitcher) { enforceStatusBar(); if (SPEW) { - Slog.d(TAG, "swetImeWindowStatus vis=" + vis + " backDisposition=" + backDisposition); + Slog.d(TAG, "setImeWindowStatus vis=" + vis + " backDisposition=" + backDisposition); } synchronized(mLock) { @@ -1289,7 +1294,9 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D private String mPackageName = "none"; private int mDisabled1 = 0; private int mDisabled2 = 0; + @InputMethodService.ImeWindowVisibility private int mImeWindowVis = 0; + @InputMethodService.BackDispositionMode private int mImeBackDisposition = 0; private boolean mShowImeSwitcher = false; private IBinder mImeToken = null; @@ -1334,7 +1341,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D return mDisabled1 == disabled1 && mDisabled2 == disabled2; } - private void setImeWindowState(final int vis, final int backDisposition, + private void setImeWindowState(@InputMethodService.ImeWindowVisibility final int vis, + @InputMethodService.BackDispositionMode final int backDisposition, final boolean showImeSwitcher, final IBinder token) { mImeWindowVis = vis; mImeBackDisposition = backDisposition;