Loading services/core/java/com/android/server/wm/DisplayContent.java +29 −12 Original line number Original line Diff line number Diff line Loading @@ -4252,6 +4252,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp void detach(Transaction t) { void detach(Transaction t) { removeImeSurface(t); removeImeSurface(t); } } @Override public String toString() { StringBuilder sb = new StringBuilder(64); sb.append("ImeScreenshot{"); sb.append(Integer.toHexString(System.identityHashCode(this))); sb.append(" imeTarget=" + mImeTarget); sb.append(" surface=" + mImeSurface); sb.append('}'); return sb.toString(); } } } private void attachAndShowImeScreenshotOnTarget() { private void attachAndShowImeScreenshotOnTarget() { Loading Loading @@ -4284,15 +4295,23 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } /** /** * Removes the IME screenshot when necessary. * Removes the IME screenshot when the caller is a part of the attached target window. * * Used when app transition animation finished or obsoleted screenshot surface like size * changed by rotation. */ */ void removeImeScreenshotIfPossible() { void removeImeSurfaceByTarget(WindowContainer win) { if (mImeLayeringTarget == null if (mImeScreenshot == null || win == null) { || mImeLayeringTarget.mAttrs.type != TYPE_APPLICATION_STARTING return; && !mImeLayeringTarget.inTransitionSelfOrParent()) { } // The starting window shouldn't be the input target to attach the IME screenshot during // transitioning. if (win.asWindowState() != null && win.asWindowState().mAttrs.type == TYPE_APPLICATION_STARTING) { return; } final WindowState screenshotTarget = mImeScreenshot.getImeTarget(); final boolean winIsOrContainsScreenshotTarget = (win == screenshotTarget || win.getWindow(w -> w == screenshotTarget) != null); if (winIsOrContainsScreenshotTarget) { removeImeSurfaceImmediately(); removeImeSurfaceImmediately(); } } } } Loading Loading @@ -4640,10 +4659,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp wc, SurfaceAnimator.animationTypeToString(type), mImeScreenshot, wc, SurfaceAnimator.animationTypeToString(type), mImeScreenshot, mImeScreenshot.getImeTarget()); mImeScreenshot.getImeTarget()); } } if (mImeScreenshot != null && (wc == mImeScreenshot.getImeTarget() if ((type & WindowState.EXIT_ANIMATING_TYPES) != 0) { || wc.getWindow(w -> w == mImeScreenshot.getImeTarget()) != null) removeImeSurfaceByTarget(wc); && (type & WindowState.EXIT_ANIMATING_TYPES) != 0) { removeImeSurfaceImmediately(); } } } } Loading services/core/java/com/android/server/wm/WindowState.java +3 −2 Original line number Original line Diff line number Diff line Loading @@ -2449,8 +2449,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final DisplayContent dc = getDisplayContent(); final DisplayContent dc = getDisplayContent(); if (isImeLayeringTarget()) { if (isImeLayeringTarget()) { // Remove the IME screenshot surface if the layering target is not animating. // Remove the attached IME screenshot surface. dc.removeImeScreenshotIfPossible(); dc.removeImeSurfaceByTarget(this); // Make sure to set mImeLayeringTarget as null when the removed window is the // Make sure to set mImeLayeringTarget as null when the removed window is the // IME target, in case computeImeTarget may use the outdated target. // IME target, in case computeImeTarget may use the outdated target. dc.setImeLayeringTarget(null); dc.setImeLayeringTarget(null); Loading Loading @@ -3584,6 +3584,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } else { } else { logExclusionRestrictions(EXCLUSION_LEFT); logExclusionRestrictions(EXCLUSION_LEFT); logExclusionRestrictions(EXCLUSION_RIGHT); logExclusionRestrictions(EXCLUSION_RIGHT); getDisplayContent().removeImeSurfaceByTarget(this); } } // Exclude toast because legacy apps may show toast window by themselves, so the misused // Exclude toast because legacy apps may show toast window by themselves, so the misused // apps won't always be considered as foreground state. // apps won't always be considered as foreground state. Loading services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +46 −0 Original line number Original line Diff line number Diff line Loading @@ -2207,6 +2207,52 @@ public class DisplayContentTests extends WindowTestsBase { assertNotEquals(curSnapshot, mDisplayContent.mImeScreenshot); assertNotEquals(curSnapshot, mDisplayContent.mImeScreenshot); } } @UseTestDisplay(addWindows = {W_INPUT_METHOD}) @Test public void testRemoveImeScreenshot_whenTargetSurfaceWasInvisible() { 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"); win.onSurfaceShownChanged(true); makeWindowVisible(win, mDisplayContent.mInputMethodWindow); task.getDisplayContent().prepareAppTransition(TRANSIT_CLOSE); doReturn(true).when(task).okToAnimate(); ArrayList<WindowContainer> sources = new ArrayList<>(); sources.add(activity); mDisplayContent.setImeLayeringTarget(win); mDisplayContent.setImeInputTarget(win); mDisplayContent.getInsetsStateController().getImeSourceProvider().setImeShowing(true); task.applyAnimation(null, TRANSIT_OLD_TASK_CLOSE, false /* enter */, false /* isVoiceInteraction */, sources); assertNotNull(mDisplayContent.mImeScreenshot); win.onSurfaceShownChanged(false); assertNull(mDisplayContent.mImeScreenshot); } @UseTestDisplay(addWindows = {W_INPUT_METHOD}) @Test public void testRemoveImeScreenshot_whenWindowRemoveImmediately() { 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"); makeWindowVisible(mDisplayContent.mInputMethodWindow); mDisplayContent.setImeLayeringTarget(win); mDisplayContent.setImeInputTarget(win); mDisplayContent.getInsetsStateController().getImeSourceProvider().setImeShowing(true); mDisplayContent.showImeScreenshot(); assertNotNull(mDisplayContent.mImeScreenshot); // Expect IME snapshot will be removed when the win is IME layering target and invoked // removeImeSurfaceByTarget. win.removeImmediately(); assertNull(mDisplayContent.mImeScreenshot); } @Test @Test public void testRotateBounds_keepSamePhysicalPosition() { public void testRotateBounds_keepSamePhysicalPosition() { final DisplayContent dc = final DisplayContent dc = Loading Loading
services/core/java/com/android/server/wm/DisplayContent.java +29 −12 Original line number Original line Diff line number Diff line Loading @@ -4252,6 +4252,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp void detach(Transaction t) { void detach(Transaction t) { removeImeSurface(t); removeImeSurface(t); } } @Override public String toString() { StringBuilder sb = new StringBuilder(64); sb.append("ImeScreenshot{"); sb.append(Integer.toHexString(System.identityHashCode(this))); sb.append(" imeTarget=" + mImeTarget); sb.append(" surface=" + mImeSurface); sb.append('}'); return sb.toString(); } } } private void attachAndShowImeScreenshotOnTarget() { private void attachAndShowImeScreenshotOnTarget() { Loading Loading @@ -4284,15 +4295,23 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } /** /** * Removes the IME screenshot when necessary. * Removes the IME screenshot when the caller is a part of the attached target window. * * Used when app transition animation finished or obsoleted screenshot surface like size * changed by rotation. */ */ void removeImeScreenshotIfPossible() { void removeImeSurfaceByTarget(WindowContainer win) { if (mImeLayeringTarget == null if (mImeScreenshot == null || win == null) { || mImeLayeringTarget.mAttrs.type != TYPE_APPLICATION_STARTING return; && !mImeLayeringTarget.inTransitionSelfOrParent()) { } // The starting window shouldn't be the input target to attach the IME screenshot during // transitioning. if (win.asWindowState() != null && win.asWindowState().mAttrs.type == TYPE_APPLICATION_STARTING) { return; } final WindowState screenshotTarget = mImeScreenshot.getImeTarget(); final boolean winIsOrContainsScreenshotTarget = (win == screenshotTarget || win.getWindow(w -> w == screenshotTarget) != null); if (winIsOrContainsScreenshotTarget) { removeImeSurfaceImmediately(); removeImeSurfaceImmediately(); } } } } Loading Loading @@ -4640,10 +4659,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp wc, SurfaceAnimator.animationTypeToString(type), mImeScreenshot, wc, SurfaceAnimator.animationTypeToString(type), mImeScreenshot, mImeScreenshot.getImeTarget()); mImeScreenshot.getImeTarget()); } } if (mImeScreenshot != null && (wc == mImeScreenshot.getImeTarget() if ((type & WindowState.EXIT_ANIMATING_TYPES) != 0) { || wc.getWindow(w -> w == mImeScreenshot.getImeTarget()) != null) removeImeSurfaceByTarget(wc); && (type & WindowState.EXIT_ANIMATING_TYPES) != 0) { removeImeSurfaceImmediately(); } } } } Loading
services/core/java/com/android/server/wm/WindowState.java +3 −2 Original line number Original line Diff line number Diff line Loading @@ -2449,8 +2449,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final DisplayContent dc = getDisplayContent(); final DisplayContent dc = getDisplayContent(); if (isImeLayeringTarget()) { if (isImeLayeringTarget()) { // Remove the IME screenshot surface if the layering target is not animating. // Remove the attached IME screenshot surface. dc.removeImeScreenshotIfPossible(); dc.removeImeSurfaceByTarget(this); // Make sure to set mImeLayeringTarget as null when the removed window is the // Make sure to set mImeLayeringTarget as null when the removed window is the // IME target, in case computeImeTarget may use the outdated target. // IME target, in case computeImeTarget may use the outdated target. dc.setImeLayeringTarget(null); dc.setImeLayeringTarget(null); Loading Loading @@ -3584,6 +3584,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } else { } else { logExclusionRestrictions(EXCLUSION_LEFT); logExclusionRestrictions(EXCLUSION_LEFT); logExclusionRestrictions(EXCLUSION_RIGHT); logExclusionRestrictions(EXCLUSION_RIGHT); getDisplayContent().removeImeSurfaceByTarget(this); } } // Exclude toast because legacy apps may show toast window by themselves, so the misused // Exclude toast because legacy apps may show toast window by themselves, so the misused // apps won't always be considered as foreground state. // apps won't always be considered as foreground state. Loading
services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +46 −0 Original line number Original line Diff line number Diff line Loading @@ -2207,6 +2207,52 @@ public class DisplayContentTests extends WindowTestsBase { assertNotEquals(curSnapshot, mDisplayContent.mImeScreenshot); assertNotEquals(curSnapshot, mDisplayContent.mImeScreenshot); } } @UseTestDisplay(addWindows = {W_INPUT_METHOD}) @Test public void testRemoveImeScreenshot_whenTargetSurfaceWasInvisible() { 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"); win.onSurfaceShownChanged(true); makeWindowVisible(win, mDisplayContent.mInputMethodWindow); task.getDisplayContent().prepareAppTransition(TRANSIT_CLOSE); doReturn(true).when(task).okToAnimate(); ArrayList<WindowContainer> sources = new ArrayList<>(); sources.add(activity); mDisplayContent.setImeLayeringTarget(win); mDisplayContent.setImeInputTarget(win); mDisplayContent.getInsetsStateController().getImeSourceProvider().setImeShowing(true); task.applyAnimation(null, TRANSIT_OLD_TASK_CLOSE, false /* enter */, false /* isVoiceInteraction */, sources); assertNotNull(mDisplayContent.mImeScreenshot); win.onSurfaceShownChanged(false); assertNull(mDisplayContent.mImeScreenshot); } @UseTestDisplay(addWindows = {W_INPUT_METHOD}) @Test public void testRemoveImeScreenshot_whenWindowRemoveImmediately() { 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"); makeWindowVisible(mDisplayContent.mInputMethodWindow); mDisplayContent.setImeLayeringTarget(win); mDisplayContent.setImeInputTarget(win); mDisplayContent.getInsetsStateController().getImeSourceProvider().setImeShowing(true); mDisplayContent.showImeScreenshot(); assertNotNull(mDisplayContent.mImeScreenshot); // Expect IME snapshot will be removed when the win is IME layering target and invoked // removeImeSurfaceByTarget. win.removeImmediately(); assertNull(mDisplayContent.mImeScreenshot); } @Test @Test public void testRotateBounds_keepSamePhysicalPosition() { public void testRotateBounds_keepSamePhysicalPosition() { final DisplayContent dc = final DisplayContent dc = Loading