Fix crash when removing a display with activities

When secondary display is removed current behavior is to
move its stacks to the primary display. This requires app
windows to be reparented, and there was a check missing
for app windows in DisplayContent.reParentWindowToken.

Test: bit FrameworksServicesTests:com.android.server.wm.DisplayContentTests
Test: #testMoveStackBetweenDisplays
Bug: 33677605
Change-Id: I2ac2cdba273134438c63385887a09c37d42017bb
This commit is contained in:
Andrii Kulian
2016-12-27 23:52:59 -08:00
parent d276563b38
commit 6cc1a1d65c
2 changed files with 40 additions and 13 deletions

View File

@@ -712,19 +712,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (prevDc == this) {
return;
}
if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null) {
switch (token.windowType) {
case TYPE_WALLPAPER:
prevDc.mBelowAppWindowsContainers.removeChild(token);
break;
case TYPE_INPUT_METHOD:
case TYPE_INPUT_METHOD_DIALOG:
prevDc.mImeWindowsContainers.removeChild(token);
break;
default:
prevDc.mAboveAppWindowsContainers.removeChild(token);
break;
}
if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null
&& token.asAppWindowToken() == null) {
// Removed the token from the map, but made sure it's not an app token before removing
// from parent.
token.getParent().removeChild(token);
}
addWindowToken(token.token, token);

View File

@@ -19,12 +19,16 @@ package com.android.server.wm;
import org.junit.Test;
import org.junit.runner.RunWith;
import android.hardware.display.DisplayManagerGlobal;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.Display;
import android.view.DisplayInfo;
import java.util.ArrayList;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static org.junit.Assert.assertEquals;
@@ -203,4 +207,35 @@ public class DisplayContentTests extends WindowTestsBase {
voiceInteractionWindow.removeImmediately();
}
@Test
public void testMoveStackBetweenDisplays() throws Exception {
// Create second display.
final Display display = new Display(DisplayManagerGlobal.getInstance(),
sDisplayContent.getDisplayId() + 1, new DisplayInfo(),
DEFAULT_DISPLAY_ADJUSTMENTS);
final DisplayContent dc = new DisplayContent(display, sWm, sLayersController,
new WallpaperController(sWm));
sWm.mRoot.addChild(dc, 1);
// Add stack with activity.
final TaskStack stack = createTaskStackOnDisplay(dc);
assertEquals(dc.getDisplayId(), stack.getDisplayContent().getDisplayId());
assertEquals(dc, stack.getParent().getParent());
assertEquals(dc, stack.getDisplayContent());
final Task task = createTaskInStack(stack, 0 /* userId */);
final TestAppWindowToken token = new TestAppWindowToken(dc);
task.addChild(token, 0);
assertEquals(dc, task.getDisplayContent());
assertEquals(dc, token.getDisplayContent());
// Move stack to first display.
sWm.moveStackToDisplay(stack.mStackId, sDisplayContent.getDisplayId());
assertEquals(sDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
assertEquals(sDisplayContent, stack.getParent().getParent());
assertEquals(sDisplayContent, stack.getDisplayContent());
assertEquals(sDisplayContent, task.getDisplayContent());
assertEquals(sDisplayContent, token.getDisplayContent());
}
}