Loading data/etc/services.core.protolog.json +18 −0 Original line number Diff line number Diff line Loading @@ -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", Loading Loading @@ -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", Loading Loading @@ -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", Loading services/core/java/com/android/server/inputmethod/InputMethodMenuController.java +27 −4 Original line number Diff line number Diff line Loading @@ -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()); Loading Loading @@ -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(); Loading services/core/java/com/android/server/wm/WindowManagerInternal.java +5 −0 Original line number Diff line number Diff line Loading @@ -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); } services/core/java/com/android/server/wm/WindowManagerService.java +31 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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 Loading services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java 0 → 100644 +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
data/etc/services.core.protolog.json +18 −0 Original line number Diff line number Diff line Loading @@ -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", Loading Loading @@ -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", Loading Loading @@ -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", Loading
services/core/java/com/android/server/inputmethod/InputMethodMenuController.java +27 −4 Original line number Diff line number Diff line Loading @@ -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()); Loading Loading @@ -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(); Loading
services/core/java/com/android/server/wm/WindowManagerInternal.java +5 −0 Original line number Diff line number Diff line Loading @@ -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); }
services/core/java/com/android/server/wm/WindowManagerService.java +31 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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 Loading
services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java 0 → 100644 +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); } }