diff options
| author | 2021-08-17 03:03:53 +0000 | |
|---|---|---|
| committer | 2021-08-17 03:03:53 +0000 | |
| commit | 7309d6a4b288ad97848971b749b0a8e3cd194adc (patch) | |
| tree | 08f20323fc042a0af472b18abe2cf65e4882d9dd | |
| parent | 3d9545ef4e7b0192ccc0ecce13aacd2b5ef05692 (diff) | |
| parent | 6b880493378abf01513b85bc2b00bdb471e3bfbf (diff) | |
Merge "Apply fixed rotation on IME window if its target is rotated" into sc-v2-dev
6 files changed, 124 insertions, 59 deletions
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 1531cd589762..fe6f2da32da4 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -4122,6 +4122,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } + /** Called right after {@link IInputMethod#showSoftInput}. */ + private void onShowHideSoftInputRequested(boolean show, IBinder requestToken, + @SoftInputShowHideReason int reason) { + final WindowManagerInternal.ImeTargetInfo info = + mWindowManagerInternal.onToggleImeRequested( + show, mCurFocusedWindow, requestToken, mCurTokenDisplayId); + mSoftInputShowHideHistory.addEntry(new SoftInputShowHideHistory.Entry( + mCurFocusedWindowClient, mCurAttribute, info.focusedWindowName, + mCurFocusedWindowSoftInputMode, reason, mInFullscreenMode, + info.requestWindowName, info.imeControlTargetName, info.imeLayerTargetName)); + } + @BinderThread private void hideMySoftInput(@NonNull IBinder token, int flags) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideMySoftInput"); @@ -4240,18 +4252,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput(" + args.arg3 + ", " + msg.arg1 + ", " + args.arg2 + ") for reason: " + InputMethodDebug.softInputDisplayReasonToString(reason)); + final IBinder token = (IBinder) args.arg3; ((IInputMethod) args.arg1).showSoftInput( - (IBinder) args.arg3, msg.arg1, (ResultReceiver) args.arg2); - mSoftInputShowHideHistory.addEntry(new SoftInputShowHideHistory.Entry( - mCurFocusedWindowClient, mCurAttribute, - mWindowManagerInternal.getWindowName(mCurFocusedWindow), - mCurFocusedWindowSoftInputMode, reason, mInFullscreenMode, - mWindowManagerInternal.getWindowName( - mShowRequestWindowMap.get(args.arg3)), - mWindowManagerInternal.getImeControlTargetNameForLogging( - mCurTokenDisplayId), - mWindowManagerInternal.getImeTargetNameForLogging( - mCurTokenDisplayId))); + token, msg.arg1 /* flags */, (ResultReceiver) args.arg2); + final IBinder requestToken = mShowRequestWindowMap.get(token); + onShowHideSoftInputRequested(true /* show */, requestToken, reason); } catch (RemoteException e) { } args.recycle(); @@ -4263,18 +4268,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, " + args.arg3 + ", " + args.arg2 + ") for reason: " + InputMethodDebug.softInputDisplayReasonToString(reason)); + final IBinder token = (IBinder) args.arg3; ((IInputMethod)args.arg1).hideSoftInput( - (IBinder) args.arg3, 0, (ResultReceiver)args.arg2); - mSoftInputShowHideHistory.addEntry(new SoftInputShowHideHistory.Entry( - mCurFocusedWindowClient, mCurAttribute, - mWindowManagerInternal.getWindowName(mCurFocusedWindow), - mCurFocusedWindowSoftInputMode, reason, mInFullscreenMode, - mWindowManagerInternal.getWindowName( - mHideRequestWindowMap.get(args.arg3)), - mWindowManagerInternal.getImeControlTargetNameForLogging( - mCurTokenDisplayId), - mWindowManagerInternal.getImeTargetNameForLogging( - mCurTokenDisplayId))); + token, 0 /* flags */, (ResultReceiver) args.arg2); + final IBinder requestToken = mHideRequestWindowMap.get(token); + onShowHideSoftInputRequested(false /* show */, requestToken, reason); } catch (RemoteException e) { } args.recycle(); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index f5f2990c500d..4aea942cce3b 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3830,6 +3830,23 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mWmService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay && !isPrivate(); } + /** @see WindowManagerInternal#onToggleImeRequested */ + void onShowImeRequested() { + if (mImeLayeringTarget == null || mInputMethodWindow == null) { + return; + } + // If IME window will be shown on the rotated activity, share the transformed state to + // IME window so it can compute rotated frame with rotated configuration. + if (mImeLayeringTarget.mToken.isFixedRotationTransforming()) { + mInputMethodWindow.mToken.linkFixedRotationTransform(mImeLayeringTarget.mToken); + // Hide the window until the rotation is done to avoid intermediate artifacts if the + // parent surface of IME container is changed. + if (mFadeRotationAnimationController != null) { + mFadeRotationAnimationController.hideImmediately(mInputMethodWindow.mToken); + } + } + } + @VisibleForTesting void setImeLayeringTarget(WindowState target) { mImeLayeringTarget = target; diff --git a/services/core/java/com/android/server/wm/FadeRotationAnimationController.java b/services/core/java/com/android/server/wm/FadeRotationAnimationController.java index eab3f108d17a..52a7ac75e2dc 100644 --- a/services/core/java/com/android/server/wm/FadeRotationAnimationController.java +++ b/services/core/java/com/android/server/wm/FadeRotationAnimationController.java @@ -42,6 +42,9 @@ public class FadeRotationAnimationController extends FadeAnimationController { /** A runnable which gets called when the {@link #show()} is called. */ private Runnable mOnShowRunnable; + /** Whether to use constant zero alpha animation. */ + private boolean mHideImmediately; + public FadeRotationAnimationController(DisplayContent displayContent) { super(displayContent); mService = displayContent.mWmService; @@ -51,6 +54,10 @@ public class FadeRotationAnimationController extends FadeAnimationController { mService.mWindowPlacerLocked.performSurfacePlacement(); } } : null; + if (mFrozenTimeoutRunnable != null) { + // Hide the windows immediately because screen should have been covered by screenshot. + mHideImmediately = true; + } final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy(); final WindowState navigationBar = displayPolicy.getNavigationBar(); if (navigationBar != null) { @@ -120,6 +127,15 @@ public class FadeRotationAnimationController extends FadeAnimationController { } } + /** Hides the window immediately until it is drawn in new rotation. */ + void hideImmediately(WindowToken windowToken) { + final boolean original = mHideImmediately; + mHideImmediately = true; + mTargetWindowTokens.add(windowToken); + fadeWindowToken(false /* show */, windowToken, ANIMATION_TYPE_FIXED_TRANSFORM); + mHideImmediately = original; + } + /** Returns {@code true} if the window is handled by this controller. */ boolean isHandledToken(WindowToken token) { return token == mNavBarToken || isTargetToken(token); @@ -145,8 +161,7 @@ public class FadeRotationAnimationController extends FadeAnimationController { @Override public Animation getFadeOutAnimation() { - if (mFrozenTimeoutRunnable != null) { - // Hide the window immediately because screen should have been covered by screenshot. + if (mHideImmediately) { return new AlphaAnimation(0 /* fromAlpha */, 0 /* toAlpha */); } return super.getFadeOutAnimation(); diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index 5bc4d4997f17..132f1392cba7 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -676,24 +676,43 @@ public abstract class WindowManagerInternal { public abstract String getWindowName(@NonNull IBinder binder); /** - * Return the window name of IME Insets control target. + * The callback after the request of show/hide input method is sent. * + * @param show Whether to show or hide input method. + * @param focusedToken The token of focused window. + * @param requestToken The token of window who requests the change. * @param displayId The ID of the display which input method is currently focused. - * @return The corresponding {@link WindowState#getName()} + * @return The information of the input method target. */ - public abstract @Nullable String getImeControlTargetNameForLogging(int displayId); + public abstract ImeTargetInfo onToggleImeRequested(boolean show, + @NonNull IBinder focusedToken, @NonNull IBinder requestToken, int displayId); - /** - * Return the current window name of the input method is on top of. - * - * Note that the concept of this window is only reparent the target window behind the input - * method window, it may different with the window which reported by - * {@code InputMethodManagerService#reportStartInput} which has input connection. - * - * @param displayId The ID of the display which input method is currently focused. - * @return The corresponding {@link WindowState#getName()} - */ - public abstract @Nullable String getImeTargetNameForLogging(int displayId); + /** The information of input method target when IME is requested to show or hide. */ + public static class ImeTargetInfo { + public final String focusedWindowName; + public final String requestWindowName; + + /** The window name of IME Insets control target. */ + public final String imeControlTargetName; + + /** + * The current window name of the input method is on top of. + * <p> + * Note that the concept of this window is only used to reparent the target window behind + * the input method window, it may be different from the window reported by + * {@link com.android.server.inputmethod.InputMethodManagerService#reportStartInput} which + * has input connection. + */ + public final String imeLayerTargetName; + + public ImeTargetInfo(String focusedWindowName, String requestWindowName, + String imeControlTargetName, String imeLayerTargetName) { + this.focusedWindowName = focusedWindowName; + this.requestWindowName = requestWindowName; + this.imeControlTargetName = imeControlTargetName; + this.imeLayerTargetName = imeLayerTargetName; + } + } /** * Moves the {@link WindowToken} {@code binder} to the display specified by {@code displayId}. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 0e25f26c5642..d139659c4baf 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -7907,30 +7907,37 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public String getImeControlTargetNameForLogging(int displayId) { + public ImeTargetInfo onToggleImeRequested(boolean show, IBinder focusedToken, + IBinder requestToken, int displayId) { + final String focusedWindowName; + final String requestWindowName; + final String imeControlTargetName; + final String imeLayerTargetName; synchronized (mGlobalLock) { + final WindowState focusedWin = mWindowMap.get(focusedToken); + focusedWindowName = focusedWin != null ? focusedWin.getName() : "null"; + final WindowState requestWin = mWindowMap.get(requestToken); + requestWindowName = requestWin != null ? requestWin.getName() : "null"; final DisplayContent dc = mRoot.getDisplayContent(displayId); - if (dc == null) { - return null; - } - final InsetsControlTarget target = dc.getImeTarget(IME_TARGET_CONTROL); - if (target == null) { - return null; - } - final WindowState win = target.getWindow(); - return win != null ? win.getName() : target.toString(); - } - } - - @Override - public String getImeTargetNameForLogging(int displayId) { - synchronized (mGlobalLock) { - final DisplayContent dc = mRoot.getDisplayContent(displayId); - if (dc == null || dc.getImeTarget(IME_TARGET_LAYERING) == null) { - return null; + if (dc != null) { + final InsetsControlTarget controlTarget = dc.getImeTarget(IME_TARGET_CONTROL); + if (controlTarget != null) { + final WindowState w = InsetsControlTarget.asWindowOrNull(controlTarget); + imeControlTargetName = w != null ? w.getName() : controlTarget.toString(); + } else { + imeControlTargetName = "null"; + } + final InsetsControlTarget target = dc.getImeTarget(IME_TARGET_LAYERING); + imeLayerTargetName = target != null ? target.getWindow().getName() : "null"; + if (show) { + dc.onShowImeRequested(); + } + } else { + imeControlTargetName = imeLayerTargetName = "no-display"; } - return dc.getImeTarget(IME_TARGET_LAYERING).getWindow().getName(); } + return new ImeTargetInfo(focusedWindowName, requestWindowName, imeControlTargetName, + imeLayerTargetName); } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index f3bb59c4598a..473d3038e3dc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -139,6 +139,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; +import com.android.server.LocalServices; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.utils.WmDisplayCutout; @@ -1307,7 +1308,7 @@ public class DisplayContentTests extends WindowTestsBase { } @UseTestDisplay(addWindows = { W_ACTIVITY, W_WALLPAPER, W_STATUS_BAR, W_NAVIGATION_BAR, - W_NOTIFICATION_SHADE }) + W_INPUT_METHOD, W_NOTIFICATION_SHADE }) @Test public void testApplyTopFixedRotationTransform() { final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy(); @@ -1411,6 +1412,14 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals("The process should receive rotated configuration for compatibility", expectedProcConfig, app2.app.getConfiguration()); + // If the rotated activity requests to show IME, the IME window should use the + // transformation from activity to lay out in the same orientation. + mDisplayContent.setImeLayeringTarget(mAppWindow); + LocalServices.getService(WindowManagerInternal.class).onToggleImeRequested(true /* show */, + app.token, app.token, mDisplayContent.mDisplayId); + assertTrue(mImeWindow.mToken.hasFixedRotationTransform()); + assertTrue(mImeWindow.isAnimating(PARENTS, ANIMATION_TYPE_FIXED_TRANSFORM)); + // The fixed rotation transform can only be finished when all animation finished. doReturn(false).when(app2).isAnimating(anyInt(), anyInt()); mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app2.token); |