Merge "Fix IME flickering when swiping out to home" into sc-qpr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c300c9d74b
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -66,8 +66,8 @@ class WallpaperWindowToken extends WindowToken {
|
||||
}
|
||||
|
||||
@Override
|
||||
void setExiting() {
|
||||
super.setExiting();
|
||||
void setExiting(boolean animateExit) {
|
||||
super.setExiting(animateExit);
|
||||
mDisplayContent.mWallpaperController.removeWallpaperToken(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user