Merge "Fix IME flickering when swiping out to home" into sc-qpr1-dev

This commit is contained in:
TreeHugger Robot
2021-08-30 12:19:53 +00:00
committed by Android (Google) Code Review
8 changed files with 98 additions and 60 deletions

View File

@@ -2582,14 +2582,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
if (mCurToken != null) {
try {
if (DEBUG) {
Slog.v(TAG, "Removing window token: " + mCurToken + " for display: "
+ mCurTokenDisplayId);
}
mIWindowManager.removeWindowToken(mCurToken, mCurTokenDisplayId);
} catch (RemoteException e) {
if (DEBUG) {
Slog.v(TAG, "Removing window token: " + mCurToken + " for display: "
+ mCurTokenDisplayId);
}
mWindowManagerInternal.removeWindowToken(mCurToken, false /* removeWindows */,
false /* animateExit */, mCurTokenDisplayId);
// Set IME window status as invisible when unbind current method.
mImeWindowVis = 0;
mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;

View File

@@ -1165,10 +1165,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
}
WindowToken removeWindowToken(IBinder binder) {
WindowToken removeWindowToken(IBinder binder, boolean animateExit) {
final WindowToken token = mTokenMap.remove(binder);
if (token != null && token.asActivityRecord() == null) {
token.setExiting();
token.setExiting(animateExit);
}
return token;
}
@@ -1252,7 +1252,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
void removeAppToken(IBinder binder) {
final WindowToken token = removeWindowToken(binder);
final WindowToken token = removeWindowToken(binder, true /* animateExit */);
if (token == null) {
Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
return;

View File

@@ -66,8 +66,8 @@ class WallpaperWindowToken extends WindowToken {
}
@Override
void setExiting() {
super.setExiting();
void setExiting(boolean animateExit) {
super.setExiting(animateExit);
mDisplayContent.mWallpaperController.removeWallpaperToken(this);
}

View File

@@ -445,8 +445,21 @@ public abstract class WindowManagerInternal {
* @param removeWindows Whether to also remove the windows associated with the token.
* @param displayId The display to remove the token from.
*/
public final void removeWindowToken(android.os.IBinder token, boolean removeWindows,
int displayId) {
removeWindowToken(token, removeWindows, true /* animateExit */, displayId);
}
/**
* Removes a window token.
*
* @param token The toke to remove.
* @param removeWindows Whether to also remove the windows associated with the token.
* @param animateExit Whether to play the windows exit animation after the token removal.
* @param displayId The display to remove the token from.
*/
public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows,
int displayId);
boolean animateExit, int displayId);
/**
* Registers a listener to be notified about app transition events.

View File

@@ -2816,6 +2816,31 @@ public class WindowManagerService extends IWindowManager.Stub
}
void removeWindowToken(IBinder binder, boolean removeWindows, boolean animateExit,
int displayId) {
synchronized (mGlobalLock) {
final DisplayContent dc = mRoot.getDisplayContent(displayId);
if (dc == null) {
ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s"
+ " for non-exiting displayId=%d", binder, displayId);
return;
}
final WindowToken token = dc.removeWindowToken(binder, animateExit);
if (token == null) {
ProtoLog.w(WM_ERROR,
"removeWindowToken: Attempted to remove non-existing token: %s",
binder);
return;
}
if (removeWindows) {
token.removeAllWindowsIfPossible();
}
dc.getInputMonitor().updateInputWindowsLw(true /* force */);
}
}
@Override
public void removeWindowToken(IBinder binder, int displayId) {
if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) {
@@ -2823,23 +2848,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
final DisplayContent dc = mRoot.getDisplayContent(displayId);
if (dc == null) {
ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s"
+ " for non-exiting displayId=%d", binder, displayId);
return;
}
final WindowToken token = dc.removeWindowToken(binder);
if (token == null) {
ProtoLog.w(WM_ERROR,
"removeWindowToken: Attempted to remove non-existing token: %s",
binder);
return;
}
dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
}
removeWindowToken(binder, false /* removeWindows */, true /* animateExit */, displayId);
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -7537,28 +7546,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
public void removeWindowToken(IBinder binder, boolean removeWindows, int displayId) {
synchronized (mGlobalLock) {
if (removeWindows) {
final DisplayContent dc = mRoot.getDisplayContent(displayId);
if (dc == null) {
ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s"
+ " for non-exiting displayId=%d", binder, displayId);
return;
}
final WindowToken token = dc.removeWindowToken(binder);
if (token == null) {
ProtoLog.w(WM_ERROR,
"removeWindowToken: Attempted to remove non-existing token: %s",
binder);
return;
}
token.removeAllWindowsIfPossible();
}
WindowManagerService.this.removeWindowToken(binder, displayId);
}
public void removeWindowToken(IBinder binder, boolean removeWindows, boolean animateExit,
int displayId) {
WindowManagerService.this.removeWindowToken(binder, removeWindows, animateExit,
displayId);
}
@Override

View File

@@ -2180,11 +2180,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
}
boolean onSetAppExiting() {
boolean onSetAppExiting(boolean animateExit) {
final DisplayContent displayContent = getDisplayContent();
boolean changed = false;
if (isVisibleNow()) {
if (!animateExit) {
// Hide the window permanently if no window exist animation is performed, so we can
// avoid the window surface becoming visible again unexpectedly during the next
// relayout.
mPermanentlyHidden = true;
hide(false /* doAnimation */, false /* requestAnim */);
}
if (isVisibleNow() && animateExit) {
mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
if (mWmService.mAccessibilityController != null) {
mWmService.mAccessibilityController.onWindowTransition(this, TRANSIT_EXIT);
@@ -2197,7 +2204,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowState c = mChildren.get(i);
changed |= c.onSetAppExiting();
changed |= c.onSetAppExiting(animateExit);
}
return changed;

View File

@@ -24,6 +24,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -232,7 +233,7 @@ class WindowToken extends WindowContainer<WindowState> {
}
}
void setExiting() {
void setExiting(boolean animateExit) {
if (isEmpty()) {
super.removeImmediately();
return;
@@ -247,11 +248,12 @@ class WindowToken extends WindowContainer<WindowState> {
final int count = mChildren.size();
boolean changed = false;
final boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN);
final boolean delayed = isAnimating(TRANSITION | PARENTS)
|| (isAnimating(CHILDREN, ANIMATION_TYPE_WINDOW_ANIMATION) && animateExit);
for (int i = 0; i < count; i++) {
final WindowState win = mChildren.get(i);
changed |= win.onSetAppExiting();
changed |= win.onSetAppExiting(animateExit);
}
final ActivityRecord app = asActivityRecord();
@@ -353,7 +355,7 @@ class WindowToken extends WindowContainer<WindowState> {
@Override
void removeImmediately() {
if (mDisplayContent != null) {
mDisplayContent.removeWindowToken(token);
mDisplayContent.removeWindowToken(token, true /* animateExit */);
}
// Needs to occur after the token is removed from the display above to avoid attempt at
// duplicate removal of this window container from it's parent.

View File

@@ -24,6 +24,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -44,6 +45,7 @@ import androidx.test.filters.SmallTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import java.util.function.BiFunction;
@@ -126,7 +128,7 @@ public class WindowTokenTests extends WindowTestsBase {
final WindowState window1 = createWindow(null, TYPE_TOAST, token, "window1");
final WindowState window2 = createWindow(null, TYPE_TOAST, token, "window2");
mDisplayContent.removeWindowToken(token.token);
mDisplayContent.removeWindowToken(token.token, true /* animateExit */);
// Verify that the token is no longer mapped on the display
assertNull(mDisplayContent.getWindowToken(token.token));
// Verify that the token is still attached to its parent
@@ -261,4 +263,29 @@ public class WindowTokenTests extends WindowTestsBase {
assertNotNull(app.getFrozenInsetsState());
assertNull(mDisplayContent.mInputMethodWindow.getFrozenInsetsState());
}
@Test
public void testRemoveWindowToken_noAnimateExitWhenSet() {
final TestWindowToken token = createTestWindowToken(0, mDisplayContent);
final WindowState win = createWindow(null, TYPE_APPLICATION, token, "win");
makeWindowVisible(win);
assertTrue(win.isOnScreen());
spyOn(win);
spyOn(win.mWinAnimator);
spyOn(win.mToken);
// Invoking removeWindowToken with setting no window exit animation and not remove window
// immediately. verify the window will hide without applying exit animation.
mWm.removeWindowToken(win.mToken.token, false /* removeWindows */, false /* animateExit */,
mDisplayContent.mDisplayId);
verify(win).onSetAppExiting(Mockito.eq(false) /* animateExit */);
verify(win).hide(false /* doAnimation */, false /* requestAnim */);
assertFalse(win.isOnScreen());
verify(win.mWinAnimator, Mockito.never()).applyAnimationLocked(TRANSIT_EXIT, false);
assertTrue(win.mToken.hasChild());
// Even though the window is being removed afterwards, it won't apply exit animation.
win.removeIfPossible();
verify(win.mWinAnimator, Mockito.never()).applyAnimationLocked(TRANSIT_EXIT, false);
}
}