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

Commit 4af9f4fc authored by Charles Chen's avatar Charles Chen
Browse files

Apply WindowContext 2.0 for InputMethodMenuController

Before WindowContext 2.0, WM creates WindowToken for each
WindowContext. After that, it only creates WindowToken when
WindowContext adss the first view.

Therefore, if InputMethodMenuController invokes getSettingsContext
with different display id before showing the IME switch dialog,
moveWindowTokenToDisplay is no-op because WindowToken with
token switchDialogToken hasn't yet existed. We should re-register
to the different display to receive ImeContainer config changes for
this scenario.

Bug: 159767464
Bug: 153369119
Test: InputMethodMenuControllerTest
Change-Id: Ib9d94a275e1b686535ab3edd7c0c3ce957efd8cd
parent 9854a1e3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@ interface IWindowManager
    // These can only be called when holding the MANAGE_APP_TOKENS permission.
    void setEventDispatching(boolean enabled);

    /** @return {@code true} if this binder is a registered window token. */
    /** Returns {@code true} if this binder is a registered window token. */
    boolean isWindowToken(in IBinder binder);
    /**
     * Adds window token for a given type.
+2 −6
Original line number Diff line number Diff line
@@ -220,7 +220,8 @@ public class InputMethodMenuController {
     */
    @VisibleForTesting
    public Context getSettingsContext(int displayId) {
        if (mSettingsContext == null) {
        // TODO(b/178462039): Cover the case when IME is moved to another ImeContainer.
        if (mSettingsContext == null || mSettingsContext.getDisplayId() != displayId) {
            final Context systemUiContext = ActivityThread.currentActivityThread()
                    .createSystemUiContext(displayId);
            final Context windowContext = systemUiContext.createWindowContext(
@@ -229,11 +230,6 @@ public class InputMethodMenuController {
                    windowContext, com.android.internal.R.style.Theme_DeviceDefault_Settings);
            mSwitchingDialogToken = mSettingsContext.getWindowContextToken();
        }
        // TODO(b/159767464): register the listener to another display again if window token is not
        // yet created.
        if (mSettingsContext.getDisplayId() != displayId) {
            mWindowManagerInternal.moveWindowTokenToDisplay(mSwitchingDialogToken, displayId);
        }
        return mSettingsContext;
    }

+14 −1
Original line number Diff line number Diff line
@@ -770,7 +770,8 @@ public class WindowManagerService extends IWindowManager.Stub
    final AnrController mAnrController;

    private final ScreenshotHashController mScreenshotHashController;
    private final WindowContextListenerController mWindowContextListenerController =
    @VisibleForTesting
    final WindowContextListenerController mWindowContextListenerController =
            new WindowContextListenerController();

    @VisibleForTesting
@@ -2794,6 +2795,17 @@ public class WindowManagerService extends IWindowManager.Stub
        return WindowManagerGlobal.ADD_OKAY;
    }

    /**
     * Registers a listener for a {@link android.app.WindowContext} to subscribe to configuration
     * changes of a {@link DisplayArea}.
     *
     * @param clientToken the window context's token
     * @param type Window type of the window context
     * @param displayId The display associated with the window context
     * @param options A bundle used to pass window-related options and choose the right DisplayArea
     *
     * @return {@code true} if the listener was registered successfully.
     */
    @Override
    public boolean registerWindowContextListener(IBinder clientToken, int type, int displayId,
            Bundle options) {
@@ -2849,6 +2861,7 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    /** Returns {@code true} if this binder is a registered window token. */
    @Override
    public boolean isWindowToken(IBinder binder) {
        synchronized (mGlobalLock) {
+12 −12
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.wm;

import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -26,7 +27,6 @@ import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;

@@ -70,13 +70,15 @@ public class InputMethodMenuControllerTest extends WindowTestsBase {
        spyOn(wms);
        doAnswer(invocation -> {
            Object[] args = invocation.getArguments();
            final IBinder token = (IBinder) args[0];
            final int windowType = (int) args[1];
            new WindowToken(mWm, token, windowType, true /* persistOnEmpty */,
                    mDefaultDisplay, true /* ownerCanManageAppTokens */, 1000 /* ownerUid */,
                    false /* roundedCornerOverlay */, true /* fromClientToken */);
            return WindowManagerGlobal.ADD_OKAY;
        }).when(wms).addWindowTokenWithOptions(any(), anyInt(), anyInt(), any(), anyString());
            IBinder clientToken = (IBinder) args[0];
            int displayId = (int) args[2];
            DisplayContent dc = mWm.mRoot.getDisplayContent(displayId);
            mWm.mWindowContextListenerController.registerWindowContainerListener(clientToken,
                    dc.getImeContainer(), 1000 /* ownerUid */, TYPE_INPUT_METHOD_DIALOG,
                    null /* options */);
            return true;
        }).when(wms).registerWindowContextListener(any(), eq(TYPE_INPUT_METHOD_DIALOG),
                anyInt(), any());

        mSecondaryDisplay = new TestDisplayContent.Builder(mAtm, 1000, 1000).build();

@@ -95,14 +97,12 @@ public class InputMethodMenuControllerTest extends WindowTestsBase {

        assertImeSwitchContextMetricsValidity(contextOnDefaultDisplay, mDefaultDisplay);

        // Obtain the context again and check they are the same instance and match the display
        // metrics of the secondary display.
        // Obtain the context again and check if the window metrics match the IME container bounds
        // of the secondary display.
        final Context contextOnSecondaryDisplay = mController.getSettingsContext(
                mSecondaryDisplay.getDisplayId());

        assertImeSwitchContextMetricsValidity(contextOnSecondaryDisplay, mSecondaryDisplay);
        assertThat(contextOnDefaultDisplay.getWindowContextToken())
                .isEqualTo(contextOnSecondaryDisplay.getWindowContextToken());
    }

    private void assertImeSwitchContextMetricsValidity(Context context, DisplayContent dc) {