summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2021-08-17 03:03:53 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-08-17 03:03:53 +0000
commit7309d6a4b288ad97848971b749b0a8e3cd194adc (patch)
tree08f20323fc042a0af472b18abe2cf65e4882d9dd
parent3d9545ef4e7b0192ccc0ecce13aacd2b5ef05692 (diff)
parent6b880493378abf01513b85bc2b00bdb471e3bfbf (diff)
Merge "Apply fixed rotation on IME window if its target is rotated" into sc-v2-dev
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java42
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java17
-rw-r--r--services/core/java/com/android/server/wm/FadeRotationAnimationController.java19
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java47
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java47
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java11
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);