Make canBeImeTarget be compatible with legacy behavior
And let PerDisplay can adjust animation parameters while the insets
source control is changed during animation.
Fix: 151759336
Test: atest WindowStateTests
Change-Id: Ic2a308e6b7ec39b4b8645751e31addd26ddf3735
(cherry picked from commit 00b9d6ed3c4982026522c4396653b8237e5447a8)
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
index 5411839..16feaad 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
@@ -177,6 +177,23 @@
int mRotation = Surface.ROTATION_0;
boolean mImeShowing = false;
+ private float mX;
+ private float mHiddenY;
+ private float mShownY;
+ private float mStartY;
+ private float mEndY;
+
+ private final Runnable mUpdateAnimationParams = () -> {
+ final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME);
+ final boolean show = mAnimationDirection == DIRECTION_SHOW;
+ final float defaultY = mImeSourceControl.getSurfacePosition().y;
+ mX = mImeSourceControl.getSurfacePosition().x;
+ mHiddenY = defaultY + imeSource.getFrame().height();
+ mShownY = defaultY;
+ mStartY = show ? mHiddenY : mShownY;
+ mEndY = show ? mShownY : mHiddenY;
+ };
+
PerDisplay(int displayId, int initialRotation) {
mDisplayId = displayId;
mRotation = initialRotation;
@@ -200,7 +217,10 @@
continue;
}
if (activeControl.getType() == InsetsState.ITYPE_IME) {
- mImeSourceControl = activeControl;
+ if (mImeSourceControl != activeControl) {
+ mImeSourceControl = activeControl;
+ mHandler.post(mUpdateAnimationParams);
+ }
}
}
}
@@ -265,28 +285,28 @@
}
mAnimationDirection = show ? DIRECTION_SHOW : DIRECTION_HIDE;
final float defaultY = mImeSourceControl.getSurfacePosition().y;
- final float x = mImeSourceControl.getSurfacePosition().x;
- final float hiddenY = defaultY + imeSource.getFrame().height();
- final float shownY = defaultY;
- final float startY = show ? hiddenY : shownY;
- final float endY = show ? shownY : hiddenY;
+ mX = mImeSourceControl.getSurfacePosition().x;
+ mHiddenY = defaultY + imeSource.getFrame().height();
+ mShownY = defaultY;
+ mStartY = show ? mHiddenY : mShownY;
+ mEndY = show ? mShownY : mHiddenY;
if (mImeShowing && show) {
// IME is already showing, so set seek to end
- seekValue = shownY;
+ seekValue = mShownY;
seek = true;
}
mImeShowing = show;
- mAnimation = ValueAnimator.ofFloat(startY, endY);
+ mAnimation = ValueAnimator.ofFloat(mStartY, mEndY);
mAnimation.setDuration(
show ? ANIMATION_DURATION_SHOW_MS : ANIMATION_DURATION_HIDE_MS);
if (seek) {
- mAnimation.setCurrentFraction((seekValue - startY) / (endY - startY));
+ mAnimation.setCurrentFraction((seekValue - mStartY) / (mEndY - mStartY));
}
mAnimation.addUpdateListener(animation -> {
SurfaceControl.Transaction t = mTransactionPool.acquire();
float value = (float) animation.getAnimatedValue();
- t.setPosition(mImeSourceControl.getLeash(), x, value);
+ t.setPosition(mImeSourceControl.getLeash(), mX, value);
dispatchPositionChanged(mDisplayId, imeTop(imeSource, value), t);
t.apply();
mTransactionPool.release(t);
@@ -297,14 +317,15 @@
@Override
public void onAnimationStart(Animator animation) {
SurfaceControl.Transaction t = mTransactionPool.acquire();
- t.setPosition(mImeSourceControl.getLeash(), x, startY);
+ t.setPosition(mImeSourceControl.getLeash(), mX, mStartY);
if (DEBUG) {
Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:"
- + imeTop(imeSource, hiddenY) + "->" + imeTop(imeSource, shownY)
+ + imeTop(imeSource, mHiddenY) + "->"
+ + imeTop(imeSource, mShownY)
+ " showing:" + (mAnimationDirection == DIRECTION_SHOW));
}
- dispatchStartPositioning(mDisplayId, imeTop(imeSource, hiddenY),
- imeTop(imeSource, shownY), mAnimationDirection == DIRECTION_SHOW,
+ dispatchStartPositioning(mDisplayId, imeTop(imeSource, mHiddenY),
+ imeTop(imeSource, mShownY), mAnimationDirection == DIRECTION_SHOW,
t);
if (mAnimationDirection == DIRECTION_SHOW) {
t.show(mImeSourceControl.getLeash());
@@ -321,7 +342,7 @@
if (DEBUG) Slog.d(TAG, "onAnimationEnd " + mCancelled);
SurfaceControl.Transaction t = mTransactionPool.acquire();
if (!mCancelled) {
- t.setPosition(mImeSourceControl.getLeash(), x, endY);
+ t.setPosition(mImeSourceControl.getLeash(), mX, mEndY);
}
dispatchEndPositioning(mDisplayId, mCancelled, t);
if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) {
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index ada6d47..85361f1 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -215,7 +215,11 @@
final Rect frame = mWin.getWindowFrames().mFrame;
if (mControl.setSurfacePosition(frame.left, frame.top) && mControlTarget != null) {
// The leash has been stale, we need to create a new one for the client.
- updateControlForTarget(mControlTarget, true /* force */);
+ if (mControlTarget != mDisplayContent.mRemoteInsetsControlTarget) {
+ // Hacky: recreating leash for RemoteInsetsControlTarget might cause IME
+ // flicker, so we just report the new surface position to it.
+ updateControlForTarget(mControlTarget, true /* force */);
+ }
mStateController.notifyControlChanged(mControlTarget);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 36175705..520a15b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -131,6 +131,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT;
import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
@@ -138,7 +139,6 @@
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
-import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT;
import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
@@ -2270,9 +2270,9 @@
return false;
}
- if (PixelFormat.formatHasAlpha(mAttrs.format) && mAttrs.alpha == 0) {
- // Support legacy use cases where completely transparent windows can still be ime target
- // with FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set.
+ if (PixelFormat.formatHasAlpha(mAttrs.format)) {
+ // Support legacy use cases where transparent windows can still be ime target with
+ // FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set.
// Certain apps listen for IME insets using transparent windows and ADJUST_NOTHING to
// manually synchronize app content to IME animation b/144619551.
// TODO(b/145812508): remove this once new focus management is complete b/141738570
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 85e4a16..e95ccab3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -251,11 +251,9 @@
// b/145812508: special legacy use-case for transparent/translucent windows.
appWindow.mAttrs.format = PixelFormat.TRANSPARENT;
- appWindow.mAttrs.alpha = 0;
assertTrue(appWindow.canBeImeTarget());
appWindow.mAttrs.format = PixelFormat.OPAQUE;
- appWindow.mAttrs.alpha = 1;
appWindow.mAttrs.flags &= ~FLAG_ALT_FOCUSABLE_IM;
assertFalse(appWindow.canBeImeTarget());
appWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE;