Fix IME snapshot missing to remove by 2 consecutive creation calls

There is a timing could happen to create another new IME snapshot
before recents animation finish, so system lost the previous
one's reference and never remove it.

Ensure removing the obsoleted IME snapshot before we create a new one.

Fix: 224664116
Test: atest DisplayContentTests#\
    testShowImeScreenshot_removeCurSnapshotBeforeCreateNext
Change-Id: I3927557453317e9beaab0d5995d6d415d09bb05d
This commit is contained in:
Ming-Shin Lu
2022-03-24 20:24:22 +08:00
parent 44b2ae6375
commit 1137b137dd
2 changed files with 30 additions and 0 deletions

View File

@@ -4143,6 +4143,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
final SurfaceControl.Transaction t = getPendingTransaction();
// Prepare IME screenshot for the target if it allows to attach into.
if (mInputMethodWindow != null && mInputMethodWindow.isVisible()) {
// Remove the obsoleted IME snapshot first in case the new snapshot happens to
// override the current one before the transition finish and the surface never be
// removed on the task.
removeImeSurfaceImmediately();
mImeScreenshot = new ImeScreenshot(
mWmService.mSurfaceControlFactory.apply(null), mImeLayeringTarget);
mImeScreenshot.attachAndShow(t);

View File

@@ -2023,6 +2023,32 @@ public class DisplayContentTests extends WindowTestsBase {
verify(mDisplayContent, never()).showImeScreenshot();
}
@UseTestDisplay(addWindows = {W_INPUT_METHOD})
@Test
public void testShowImeScreenshot_removeCurSnapshotBeforeCreateNext() {
final Task rootTask = createTask(mDisplayContent);
final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win");
mDisplayContent.setImeLayeringTarget(win);
mDisplayContent.setImeInputTarget(win);
spyOn(mDisplayContent);
spyOn(mDisplayContent.mInputMethodWindow);
doReturn(true).when(mDisplayContent.mInputMethodWindow).isVisible();
mDisplayContent.getInsetsStateController().getImeSourceProvider().setImeShowing(true);
// Verify when the timing of 2 showImeScreenshot invocations are very close, will first
// detach the current snapshot then create the next one.
mDisplayContent.showImeScreenshot();
DisplayContent.ImeScreenshot curSnapshot = mDisplayContent.mImeScreenshot;
spyOn(curSnapshot);
mDisplayContent.showImeScreenshot();
verify(curSnapshot).detach(any());
assertNotNull(mDisplayContent.mImeScreenshot);
assertNotEquals(curSnapshot, mDisplayContent.mImeScreenshot);
}
@Test
public void testRotateBounds_keepSamePhysicalPosition() {
final DisplayContent dc =