Keep IME above starting window.
While app window is animating-in, IME window is child of aboveAppContainers. If app requests IME on activity resume, IME will start animating-in above Snapshot during app window animation. However when app window animation finishes, IME's parent is no longer aboveAppContainers, thereby making snapshot occlude IME briefly. This results in flashing. The fix is to keep IME in aboveAppContainers as long as startingWindow is not removed from hierarchy. Bug: 137534359 Test: Manual and atest ZOrderingTests AppWindowTokenTests Change-Id: I78c939e8d1f23144162ba9eb8d834150fdd08ae8
This commit is contained in:
@@ -206,6 +206,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
boolean removed;
|
||||
|
||||
// Information about an application starting window if displayed.
|
||||
// Note: these are de-referenced before the starting window animates away.
|
||||
StartingData mStartingData;
|
||||
WindowState startingWindow;
|
||||
StartingSurface startingSurface;
|
||||
@@ -1243,6 +1244,21 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if starting window is in app's hierarchy.
|
||||
*/
|
||||
boolean hasStartingWindow() {
|
||||
if (startingDisplayed || mStartingData != null) {
|
||||
return true;
|
||||
}
|
||||
for (int i = mChildren.size() - 1; i >= 0; i--) {
|
||||
if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
void addWindow(WindowState w) {
|
||||
super.addWindow(w);
|
||||
|
||||
@@ -4845,9 +4845,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
//
|
||||
// In the case where we have no IME target we assign it where it's base layer would
|
||||
// place it in the AboveAppWindowContainers.
|
||||
if (imeTarget != null && !(imeTarget.inSplitScreenWindowingMode()
|
||||
|| imeTarget.mToken.isAppAnimating())
|
||||
&& (imeTarget.getSurfaceControl() != null)) {
|
||||
//
|
||||
// Keep IME window in mAboveAppWindowsContainers as long as app's starting window exists
|
||||
// so it get's layered above the starting window.
|
||||
if (imeTarget != null
|
||||
&& !(imeTarget.mAppToken != null && imeTarget.mAppToken.hasStartingWindow())
|
||||
&& (!(imeTarget.inSplitScreenWindowingMode() || imeTarget.mToken.isAppAnimating())
|
||||
&& (imeTarget.getSurfaceControl() != null))) {
|
||||
mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
|
||||
// TODO: We need to use an extra level on the app surface to ensure
|
||||
// this is always above SurfaceView but always below attached window.
|
||||
|
||||
@@ -504,6 +504,21 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
||||
assertEquals(stackBounds, mToken.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasStartingWindow() {
|
||||
final WindowManager.LayoutParams attrs =
|
||||
new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING);
|
||||
final WindowTestUtils.TestWindowState startingWindow = createWindowState(attrs, mToken);
|
||||
mToken.startingDisplayed = true;
|
||||
mToken.addWindow(startingWindow);
|
||||
assertTrue("Starting window should be present", mToken.hasStartingWindow());
|
||||
mToken.startingDisplayed = false;
|
||||
assertTrue("Starting window should be present", mToken.hasStartingWindow());
|
||||
|
||||
mToken.removeChild(startingWindow);
|
||||
assertFalse("Starting window should not be present", mToken.hasStartingWindow());
|
||||
}
|
||||
|
||||
private void assertHasStartingWindow(AppWindowToken atoken) {
|
||||
assertNotNull(atoken.startingSurface);
|
||||
assertNotNull(atoken.mStartingData);
|
||||
|
||||
Reference in New Issue
Block a user