Fix shared dim layer not cleared when all users removed

For secondary display, shared fullscreen dim layer user is
the only stack that is present on the display. When this stack
is removed the shared dim layer was not cleared. Because of
that it was crashing when trying to obtain DisplayContent from it.

Now when we're removing a dim layer user we check if we've removed
the last one and clear shared fullscreen dim layer if needed.

Bug: 34367817
Test: bit FrameworksServicesTests:com.android.server.wm.DimLayerControllerTests
Change-Id: I415196a345c491eddd26a55370bb819ce6485151
This commit is contained in:
Andrii Kulian
2017-01-25 19:45:34 -08:00
parent b922d1f9e6
commit 367ff7fd52
8 changed files with 130 additions and 24 deletions

View File

@@ -322,6 +322,9 @@ class DimLayerController {
}
mState.remove(dimLayerUser);
}
if (mState.isEmpty()) {
mSharedFullScreenDimLayer = null;
}
}
@VisibleForTesting
@@ -329,6 +332,11 @@ class DimLayerController {
return mState.containsKey(dimLayerUser);
}
@VisibleForTesting
boolean hasSharedFullScreenDimLayer() {
return mSharedFullScreenDimLayer != null;
}
void applyDimBehind(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) {
applyDim(dimLayerUser, animator, false /* aboveApp */);
}

View File

@@ -627,6 +627,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
};
/**
* Create new {@link DisplayContent} instance, add itself to the root window container and
* initialize direct children.
* @param display May not be null.
* @param service You know.
* @param layersController window layer controller used to assign layer to the windows on this
@@ -661,6 +663,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
super.addChild(mTaskStackContainers, null);
super.addChild(mAboveAppWindowsContainers, null);
super.addChild(mImeWindowsContainers, null);
// Add itself as a child to the root container.
mService.mRoot.addChild(this, null);
}
int getDisplayId() {

View File

@@ -213,7 +213,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
final int displayId = display.getDisplayId();
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
addChild(dc, null);
final DisplayInfo displayInfo = dc.getDisplayInfo();
final Rect rect = new Rect();

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.server.wm;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
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 org.junit.Test;
import org.junit.runner.RunWith;
/**
* Tests for the {@link DimLayerController} class.
*
* Build/Install/Run:
* bit FrameworksServicesTests:com.android.server.wm.DimLayerControllerTests
*/
@SmallTest
@Presubmit
@org.junit.runner.RunWith(AndroidJUnit4.class)
public class DimLayerControllerTests extends WindowTestsBase {
/**
* This tests if shared fullscreen dim layer is added when stack is added to display
* and is removed when the only stack on the display is removed.
*/
@Test
public void testSharedFullScreenDimLayer() throws Exception {
// Create a display.
final DisplayContent dc = createNewDisplay();
assertFalse(dc.mDimLayerController.hasSharedFullScreenDimLayer());
// Add stack with activity.
final TaskStack stack = createTaskStackOnDisplay(dc);
assertTrue(dc.mDimLayerController.hasDimLayerUser(stack));
assertTrue(dc.mDimLayerController.hasSharedFullScreenDimLayer());
// Remove the only stack on the display and check if the shared dim layer clears.
stack.removeImmediately();
assertFalse(dc.mDimLayerController.hasDimLayerUser(stack));
assertFalse(dc.mDimLayerController.hasSharedFullScreenDimLayer());
}
}

View File

@@ -29,6 +29,7 @@ import android.view.DisplayInfo;
import java.util.ArrayList;
import static android.view.Display.DEFAULT_DISPLAY;
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;
@@ -215,13 +216,8 @@ public class DisplayContentTests extends WindowTestsBase {
*/
@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);
// Create a second display.
final DisplayContent dc = createNewDisplay();
// Add stack with activity.
final TaskStack stack = createTaskStackOnDisplay(dc);
@@ -261,10 +257,31 @@ public class DisplayContentTests extends WindowTestsBase {
// Check that override config is applied.
assertEquals(newOverrideConfig, sDisplayContent.getOverrideConfiguration());
}
/**
* This tests global configuration updates when default display config is updated.
*/
@Test
public void testDefaultDisplayOverrideConfigUpdate() throws Exception {
final Configuration currentOverrideConfig = sDisplayContent.getOverrideConfiguration();
// Create new, slightly changed override configuration and apply it to the display.
final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
newOverrideConfig.densityDpi += 120;
newOverrideConfig.fontScale += 0.3;
sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY);
// Check that global configuration is updated, as we've updated default display's config.
final Configuration globalConfig = sWm.mRoot.getConfiguration();
Configuration globalConfig = sWm.mRoot.getConfiguration();
assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
// Return back to original values.
sWm.setNewDisplayOverrideConfiguration(currentOverrideConfig, DEFAULT_DISPLAY);
globalConfig = sWm.mRoot.getConfiguration();
assertEquals(currentOverrideConfig.densityDpi, globalConfig.densityDpi);
assertEquals(currentOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
}
}

View File

@@ -102,12 +102,7 @@ public class StackWindowControllerTests extends WindowTestsBase {
task1.mOnDisplayChangedCalled = false;
// Create second display and put second stack on it.
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);
final DisplayContent dc = createNewDisplay();
final StackWindowController stack2Controller =
createStackControllerOnDisplay(dc);
final TaskStack stack2 = stack2Controller.mContainer;

View File

@@ -128,13 +128,10 @@ public class TaskWindowContainerControllerTests extends WindowTestsBase {
new TestTaskWindowContainerController(stack1Controller);
final TestTask task1 = (TestTask) taskController.mContainer;
task1.mOnDisplayChangedCalled = false;
assertEquals(sDisplayContent, stack1.getDisplayContent());
// Create second display and put second stack on it.
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);
final DisplayContent dc = createNewDisplay();
final StackWindowController stack2Controller = createStackControllerOnDisplay(dc);
final TaskStack stack2 = stack2Controller.mContainer;
final TestTaskWindowContainerController taskController2 =

View File

@@ -20,7 +20,10 @@ import android.app.ActivityManager.TaskDescription;
import android.app.ActivityManagerInternal;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Binder;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.IApplicationToken;
import org.junit.Assert;
import org.junit.Before;
@@ -40,6 +43,7 @@ import static android.app.AppOpsManager.OP_NONE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.EMPTY;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -65,11 +69,13 @@ class WindowTestsBase {
static TestWindowManagerPolicy sPolicy = null;
private final static IWindow sIWindow = new TestIWindow();
private final static Session sMockSession = mock(Session.class);
private static int sNextDisplayId = Display.DEFAULT_DISPLAY + 1;
static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
private static int sNextTaskId = 0;
private static boolean sOneTimeSetupDone = false;
static DisplayContent sDisplayContent;
static DisplayInfo sDisplayInfo = new DisplayInfo();
static WindowLayersController sLayersController;
static WindowState sWallpaperWindow;
static WindowState sImeWindow;
@@ -100,9 +106,15 @@ class WindowTestsBase {
if (sDisplayContent != null) {
sDisplayContent.removeImmediately();
}
sDisplayContent = new DisplayContent(context.getDisplay(), sWm, sLayersController,
new WallpaperController(sWm));
sWm.mRoot.addChild(sDisplayContent, 0);
// Make sure that display ids don't overlap, so there won't be several displays with same
// ids among RootWindowContainer children.
for (DisplayContent dc : sWm.mRoot.mChildren) {
if (dc.getDisplayId() >= sNextDisplayId) {
sNextDisplayId = dc.getDisplayId() + 1;
}
}
context.getDisplay().getDisplayInfo(sDisplayInfo);
sDisplayContent = createNewDisplay();
sWm.mDisplayEnabled = true;
sWm.mDisplayReady = true;
@@ -187,7 +199,7 @@ class WindowTestsBase {
true /* onTop */, new Rect(), sWm);
}
/**Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
/** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
static Task createTaskInStack(TaskStack stack, int userId) {
final Task newTask = new Task(sNextTaskId++, stack, userId, sWm, null, EMPTY, false, 0,
false, false, new TaskDescription(), null);
@@ -195,6 +207,14 @@ class WindowTestsBase {
return newTask;
}
/** Creates a {@link DisplayContent} and adds it to the system. */
DisplayContent createNewDisplay() {
final int displayId = sNextDisplayId++;
final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
sDisplayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
return new DisplayContent(display, sWm, sLayersController, new WallpaperController(sWm));
}
/* Used so we can gain access to some protected members of the {@link WindowToken} class */
static class TestWindowToken extends WindowToken {