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

Commit 6634f53d authored by Charles Chen's avatar Charles Chen Committed by Android (Google) Code Review
Browse files

Merge "Migrate IME switch dialog to WindowContext"

parents 8b483861 9329fbdd
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -2467,6 +2467,12 @@
      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
    },
    "781471998": {
      "message": "moveWindowTokenToDisplay: Cannot move to the original display for token: %s",
      "level": "WARN",
      "group": "WM_ERROR",
      "at": "com\/android\/server\/wm\/WindowManagerService.java"
    },
    "791468751": {
      "message": "Pausing rotation during re-position",
      "level": "DEBUG",
@@ -2671,6 +2677,12 @@
      "group": "WM_DEBUG_STATES",
      "at": "com\/android\/server\/wm\/ActivityRecord.java"
    },
    "1033274509": {
      "message": "moveWindowTokenToDisplay: Attempted to move non-existing token: %s",
      "level": "WARN",
      "group": "WM_ERROR",
      "at": "com\/android\/server\/wm\/WindowManagerService.java"
    },
    "1040675582": {
      "message": "Can't report activity configuration update - client not running, activityRecord=%s",
      "level": "WARN",
@@ -3457,6 +3469,12 @@
      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
      "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
    },
    "2060978050": {
      "message": "moveWindowTokenToDisplay: Attempted to move token: %s to non-exiting displayId=%d",
      "level": "WARN",
      "group": "WM_ERROR",
      "at": "com\/android\/server\/wm\/WindowManagerService.java"
    },
    "2081291430": {
      "message": "Focus not requested for window=%s because it has no surface",
      "level": "DEBUG",
+27 −4
Original line number Diff line number Diff line
@@ -136,10 +136,7 @@ public class InputMethodMenuController {
                }
            }

            final ActivityThread currentThread = ActivityThread.currentActivityThread();
            final Context settingsContext = new ContextThemeWrapper(
                    currentThread.createSystemUiContext(displayId),
                    com.android.internal.R.style.Theme_DeviceDefault_Settings);
            final Context settingsContext = getSettingsContext(displayId);
            mDialogBuilder = new AlertDialog.Builder(settingsContext);
            mDialogBuilder.setOnCancelListener(dialog -> hideInputMethodMenu());

@@ -214,6 +211,32 @@ public class InputMethodMenuController {
        }
    }

    /**
     * Returns the window context for IME switch dialogs to receive configuration changes.
     *
     * This method initializes the window context if it was not initialized. This method also moves
     * the context to the targeted display if the current display of context is different than
     * the display specified by {@code displayId}.
     */
    @VisibleForTesting
    public Context getSettingsContext(int displayId) {
        if (mSettingsContext == null) {
            final Context systemUiContext = ActivityThread.currentActivityThread()
                    .createSystemUiContext(displayId);
            final Context windowContext = systemUiContext.createWindowContext(
                    WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG, null /* options */);
            mSettingsContext = new ContextThemeWrapper(
                    windowContext, com.android.internal.R.style.Theme_DeviceDefault_Settings);
            mSwitchingDialogToken = mSettingsContext.getActivityToken();
        }
        // 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;
    }

    private boolean isScreenLocked() {
        return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked()
                && mKeyguardManager.isKeyguardSecure();
+5 −0
Original line number Diff line number Diff line
@@ -597,4 +597,9 @@ public abstract class WindowManagerInternal {
     * @return The corresponding {@link WindowState#getName()}
     */
    public abstract @Nullable String getImeTargetNameForLogging(int displayId);

    /**
     * Moves the {@link WindowToken} {@code binder} to the display specified by {@code displayId}.
     */
    public abstract void moveWindowTokenToDisplay(IBinder binder, int displayId);
}
+31 −0
Original line number Diff line number Diff line
@@ -2723,6 +2723,32 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    /** @see WindowManagerInternal#moveWindowTokenToDisplay(IBinder, int)  */
    public void moveWindowTokenToDisplay(IBinder binder, int displayId) {
        synchronized (mGlobalLock) {
            final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
            if (dc == null) {
                ProtoLog.w(WM_ERROR, "moveWindowTokenToDisplay: Attempted to move token: %s"
                        + " to non-exiting displayId=%d", binder, displayId);
                return;
            }
            final WindowToken token = mRoot.getWindowToken(binder);
            if (token == null) {
                ProtoLog.w(WM_ERROR,
                        "moveWindowTokenToDisplay: Attempted to move non-existing token: %s",
                        binder);
                return;
            }
            if (token.getDisplayContent() == dc) {
                ProtoLog.w(WM_ERROR,
                        "moveWindowTokenToDisplay: Cannot move to the original display "
                                + "for token: %s", binder);
                return;
            }
            dc.reParentWindowToken(token);
        }
    }

    void setNewDisplayOverrideConfiguration(Configuration overrideConfig,
            @NonNull DisplayContent dc) {
        if (dc.mWaitingForConfig) {
@@ -7355,6 +7381,11 @@ public class WindowManagerService extends IWindowManager.Stub
            }
        }

        @Override
        public void moveWindowTokenToDisplay(IBinder binder, int displayId) {
            WindowManagerService.this.moveWindowTokenToDisplay(binder, displayId);
        }

        // TODO(multi-display): currently only used by PWM to notify keyguard transitions as well
        // forwarding it to SystemUI for synchronizing status and navigation bar animations.
        @Override
+78 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm;

import static android.view.Display.DEFAULT_DISPLAY;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.mock;

import android.content.Context;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.WindowManager;

import com.android.server.inputmethod.InputMethodManagerService;
import com.android.server.inputmethod.InputMethodMenuController;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

// TODO(b/157888351): Move the test to inputmethod package once we find the way to test the
//  scenario there.
/**
 * Build/Install/Run:
 *  atest WmTests:InputMethodMenuControllerTest
 */
@Presubmit
@RunWith(WindowTestRunner.class)
public class InputMethodMenuControllerTest extends WindowTestsBase {

    private InputMethodMenuController mController;

    @Before
    public void setUp() {
        mController = new InputMethodMenuController(mock(InputMethodManagerService.class));
    }

    @Test
    public void testGetSettingsContext() {
        final Context contextOnDefaultDisplay = mController.getSettingsContext(DEFAULT_DISPLAY);

        assertImeSwitchContextMetricsValidity(contextOnDefaultDisplay, mDefaultDisplay);

        // Obtain the context again and check they are the same instance and match the display
        // metrics of the secondary display.
        final Context contextOnSecondaryDisplay = mController.getSettingsContext(
                mDisplayContent.getDisplayId());

        assertImeSwitchContextMetricsValidity(contextOnSecondaryDisplay, mDisplayContent);
        assertThat(contextOnDefaultDisplay.getActivityToken())
                .isEqualTo(contextOnSecondaryDisplay.getActivityToken());
    }

    private void assertImeSwitchContextMetricsValidity(Context context, DisplayContent dc) {
        assertThat(context.getDisplayId()).isEqualTo(dc.getDisplayId());

        final Rect contextBounds = context.getSystemService(WindowManager.class)
                .getMaximumWindowMetrics().getBounds();
        final Rect imeContainerBounds = dc.getImeContainer().getBounds();
        assertThat(contextBounds).isEqualTo(imeContainerBounds);
    }
}
Loading