Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit efe4c6ef authored by Cosmin Băieș's avatar Cosmin Băieș Committed by Android (Google) Code Review
Browse files

Merge "Check system nav bar for custom IME Switcher vis" into main

parents d321887e 3a0f01da
Loading
Loading
Loading
Loading
+41 −18
Original line number Diff line number Diff line
@@ -434,6 +434,11 @@ public class InputMethodService extends AbstractInputMethodService {
        return SystemProperties.getBoolean(PROP_CAN_RENDER_GESTURAL_NAV_BUTTONS, true);
    }

    /**
     * Cached value of {@link #canImeRenderGesturalNavButtons}, as it doesn't change at runtime.
     */
    private final boolean mCanImeRenderGesturalNavButtons = canImeRenderGesturalNavButtons();

    /**
     * Allows the system to optimize the back button affordance based on the presence of software
     * keyboard.
@@ -564,6 +569,9 @@ public class InputMethodService extends AbstractInputMethodService {
    private final NavigationBarController mNavigationBarController =
            new NavigationBarController(this);

    /** Whether a custom IME Switcher button was requested to be visible. */
    private boolean mCustomImeSwitcherButtonRequestedVisible;

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    int mTheme = 0;

@@ -783,7 +791,7 @@ public class InputMethodService extends AbstractInputMethodService {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initializeInternal");
            mPrivOps.set(params.privilegedOperations);
            InputMethodPrivilegedOperationsRegistry.put(params.token, mPrivOps);
            mNavigationBarController.onNavButtonFlagsChanged(params.navigationBarFlags);
            onNavButtonFlagsChanged(params.navigationBarFlags);
            attachToken(params.token);
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
@@ -893,7 +901,7 @@ public class InputMethodService extends AbstractInputMethodService {
        public final void dispatchStartInput(@Nullable InputConnection inputConnection,
                @NonNull IInputMethod.StartInputParams params) {
            mPrivOps.reportStartInputAsync(params.startInputToken);
            mNavigationBarController.onNavButtonFlagsChanged(params.navigationBarFlags);
            onNavButtonFlagsChanged(params.navigationBarFlags);
            if (params.restarting) {
                restartInput(inputConnection, params.editorInfo);
            } else {
@@ -918,6 +926,20 @@ public class InputMethodService extends AbstractInputMethodService {
        @Override
        public void onNavButtonFlagsChanged(@InputMethodNavButtonFlags int navButtonFlags) {
            mNavigationBarController.onNavButtonFlagsChanged(navButtonFlags);
            if (!mCanImeRenderGesturalNavButtons) {
                final boolean showImeSwitcher = (navButtonFlags
                        & InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN) != 0;
                // The IME cannot draw the IME nav bar, so this will never be visible. In this case
                // the system nav bar hosts the IME buttons.
                // The system nav bar will be hidden when the IME is shown and the config is set.
                final boolean navBarNotVisible = getApplicationContext().getResources()
                        .getBoolean(com.android.internal.R.bool.config_hideNavBarForKeyboard);
                final boolean visible = showImeSwitcher && navBarNotVisible;
                if (visible != mCustomImeSwitcherButtonRequestedVisible) {
                    mCustomImeSwitcherButtonRequestedVisible = visible;
                    onCustomImeSwitcherButtonRequestedVisible(visible);
                }
            }
        }

        /**
@@ -4473,28 +4495,27 @@ public class InputMethodService extends AbstractInputMethodService {
    /**
     * Called when the requested visibility of a custom IME Switcher button changes.
     *
     * <p>When the system provides an IME navigation bar, it may decide to show an IME Switcher
     * button inside this bar. However, the IME can request hiding the bar provided by the system
     * with {@code getWindowInsetsController().hide(captionBar())} (the IME navigation bar provides
     * {@link Type#captionBar() captionBar} insets to the IME window). If the request is successful,
     * then it becomes the IME's responsibility to provide a custom IME Switcher button in its
     * input view, with equivalent functionality.</p>
     * <p>When this method is called with {@code true} by the system, the IME must show a button
     * within its UI to switch IMEs. When it is called with {@code false}, it must hide this button.
     *
     * <p>Normally, the system provides a button for switching to a different IME when that is
     * appropriate. Under certain circumstances, namely when the IME successfully asks to hide the
     * system-provided navigation bar (with {@code getWindowInsetsController().hide(captionBar())}),
     * providing this button is delegated to the IME through this callback.
     *
     * <p>This custom button is only requested to be visible when the system provides the IME
     * navigation bar, both the bar and the IME Switcher button inside it should be visible,
     * but the IME successfully requested to hide the bar. This does not depend on the current
     * visibility of the IME. It could be called with {@code true} while the IME is hidden, in
     * which case the IME should prepare to show the button as soon as the IME itself is shown.</p>
     * <p>This does not depend on the current visibility of the IME. It could be called with
     * {@code true} while the IME is hidden, in which case the IME should prepare to show the button
     * as soon as the IME itself is shown.
     *
     * <p>This is only called when the requested visibility changes. The default value is
     * {@code false} and as such, this will not be called initially if the resulting value is
     * {@code false}.</p>
     * {@code false}.
     *
     * <p>This can be called at any time after {@link #onCreate}, even if the IME is not currently
     * visible. However, this is not guaranteed to be called before the IME is shown, as it depends
     * on when the IME requested hiding the IME navigation bar. If the request is sent during
     * the showing flow (e.g. during {@link #onStartInputView}), this will be called shortly after
     * {@link #onWindowShown}, but before the first IME frame is drawn.</p>
     * visible. However, this is not guaranteed to be called before the IME is shown, as it may
     * depend on the IME requesting to hide the system-provided navigation bar. If the request is
     * sent during the showing flow (e.g. during {@link #onStartInputView}), this will be called
     * shortly after {@link #onWindowShown}, but before the first IME frame is drawn.
     *
     * @param visible whether the button is requested visible or not.
     */
@@ -4686,6 +4707,8 @@ public class InputMethodService extends AbstractInputMethodService {
                + " touchableRegion=" + mTmpInsets.touchableRegion);
        p.println("  mSettingsObserver=" + mSettingsObserver);
        p.println("  mNavigationBarController=" + mNavigationBarController.toDebugString());
        p.println("  mCustomImeSwitcherButtonRequestedVisible="
                + mCustomImeSwitcherButtonRequestedVisible);
    }

    private final ImeTracing.ServiceDumper mDumper = new ImeTracing.ServiceDumper() {
+42 −34
Original line number Diff line number Diff line
@@ -170,6 +170,9 @@ final class NavigationBarController {

        private boolean mShouldShowImeSwitcherWhenImeIsShown;

        /** Whether a custom IME Switcher button should be visible. */
        private boolean mCustomImeSwitcherButtonRequestedVisible;

        @Appearance
        private int mAppearance;

@@ -181,9 +184,6 @@ final class NavigationBarController {

        private boolean mDrawLegacyNavigationBarBackground;

        /** Whether a custom IME Switcher button should be visible. */
        private boolean mCustomImeSwitcherVisible;

        private final Rect mTempRect = new Rect();
        private final int[] mTempPos = new int[2];

@@ -275,7 +275,9 @@ final class NavigationBarController {
                    // IME navigation bar.
                    boolean visible = insets.isVisible(captionBar());
                    mNavigationBarFrame.setVisibility(visible ? View.VISIBLE : View.GONE);
                    checkCustomImeSwitcherVisibility();
                    checkCustomImeSwitcherButtonRequestedVisible(
                            mShouldShowImeSwitcherWhenImeIsShown, mImeDrawsImeNavBar,
                            !visible /* imeNavBarNotVisible */);
                }
                return view.onApplyWindowInsets(insets);
            });
@@ -502,22 +504,15 @@ final class NavigationBarController {
                    mShouldShowImeSwitcherWhenImeIsShown;
            mShouldShowImeSwitcherWhenImeIsShown = shouldShowImeSwitcherWhenImeIsShown;

            checkCustomImeSwitcherVisibility();

            mService.mWindow.getWindow().getDecorView().getWindowInsetsController()
                    .setImeCaptionBarInsetsHeight(getImeCaptionBarHeight(imeDrawsImeNavBar));

            if (imeDrawsImeNavBar) {
                installNavigationBarFrameIfNecessary();
                if (mNavigationBarFrame == null) {
                    return;
                }
                if (mShouldShowImeSwitcherWhenImeIsShown
                        == prevShouldShowImeSwitcherWhenImeIsShown) {
                    return;
                }
                final NavigationBarView navigationBarView = mNavigationBarFrame.findViewByPredicate(
                        NavigationBarView.class::isInstance);
                if (mNavigationBarFrame != null && mShouldShowImeSwitcherWhenImeIsShown
                        != prevShouldShowImeSwitcherWhenImeIsShown) {
                    final NavigationBarView navigationBarView = mNavigationBarFrame
                            .findViewByPredicate(NavigationBarView.class::isInstance);
                    if (navigationBarView != null) {
                        // TODO(b/213337792): Support InputMethodService#setBackDisposition().
                        // TODO(b/213337792): Set NAVBAR_IME_VISIBLE only when necessary.
@@ -526,9 +521,14 @@ final class NavigationBarController {
                                ? NAVBAR_IME_SWITCHER_BUTTON_VISIBLE : 0);
                        navigationBarView.setNavbarFlags(flags);
                    }
                }
            } else {
                uninstallNavigationBarFrameIfNecessary();
            }

            // Check custom IME Switcher button visibility after (un)installing nav bar frame.
            checkCustomImeSwitcherButtonRequestedVisible(shouldShowImeSwitcherWhenImeIsShown,
                    imeDrawsImeNavBar, !isShown() /* imeNavBarNotVisible */);
        }

        @Override
@@ -631,22 +631,29 @@ final class NavigationBarController {
        }

        /**
         * Checks if a custom IME Switcher button should be visible, and notifies the IME when this
         * state changes. This can only be {@code true} if three conditions are met:
         * Checks if a custom IME Switcher button should be requested visible, and notifies the IME
         * when this state changes. This is only {@code true} when the IME Switcher button is
         * requested visible, and the navigation bar is not requested visible.
         *
         * <li>The IME should draw the IME navigation bar.</li>
         * <li>The IME Switcher button should be visible when the IME is visible.</li>
         * <li>The IME navigation bar should be visible, but was requested hidden by the IME.</li>
         * @param buttonVisible       whether the IME Switcher button is requested visible.
         * @param shouldDrawImeNavBar whether the IME navigation bar should be drawn.
         * @param imeNavBarNotVisible whether the IME navigation bar is not requested visible. This
         *                            will be {@code true} if it is requested hidden or not
         *                            installed.
         */
        private void checkCustomImeSwitcherVisibility() {
        private void checkCustomImeSwitcherButtonRequestedVisible(boolean buttonVisible,
                boolean shouldDrawImeNavBar, boolean imeNavBarNotVisible) {
            if (!Flags.imeSwitcherRevampApi()) {
                return;
            }
            final boolean visible = mImeDrawsImeNavBar && mShouldShowImeSwitcherWhenImeIsShown
                    && mNavigationBarFrame != null && !isShown();
            if (visible != mCustomImeSwitcherVisible) {
                mCustomImeSwitcherVisible = visible;
                mService.onCustomImeSwitcherButtonRequestedVisible(mCustomImeSwitcherVisible);
            // The system nav bar will be hidden when the IME is shown and the config is set.
            final boolean navBarNotVisible = shouldDrawImeNavBar ? imeNavBarNotVisible
                    : mService.getResources().getBoolean(
                            com.android.internal.R.bool.config_hideNavBarForKeyboard);
            final boolean visible = buttonVisible && navBarNotVisible;
            if (visible != mCustomImeSwitcherButtonRequestedVisible) {
                mCustomImeSwitcherButtonRequestedVisible = visible;
                mService.onCustomImeSwitcherButtonRequestedVisible(visible);
            }
        }

@@ -656,7 +663,8 @@ final class NavigationBarController {
                    + " mNavigationBarFrame=" + mNavigationBarFrame
                    + " mShouldShowImeSwitcherWhenImeIsShown="
                    + mShouldShowImeSwitcherWhenImeIsShown
                    + " mCustomImeSwitcherVisible="  + mCustomImeSwitcherVisible
                    + " mCustomImeSwitcherButtonRequestedVisible="
                    + mCustomImeSwitcherButtonRequestedVisible
                    + " mAppearance=0x" + Integer.toHexString(mAppearance)
                    + " mDarkIntensity=" + mDarkIntensity
                    + " mDrawLegacyNavigationBarBackground=" + mDrawLegacyNavigationBarBackground