Starting window tests, yay!
Test: bit FrameworksServicesTests:com.android.server.wm.AppWindowContainerControllerTests Fixes: 34364463 Fixes: 34361417 Change-Id: Ie1b8debc894e5cad8fe517912a1991a38661dfaa
This commit is contained in:
@@ -56,7 +56,7 @@ public class AppWindowContainerController
|
||||
private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
|
||||
|
||||
private final IApplicationToken mToken;
|
||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private final Handler mHandler;
|
||||
|
||||
private final Runnable mOnWindowsDrawn = () -> {
|
||||
if (mListener == null) {
|
||||
@@ -186,6 +186,7 @@ public class AppWindowContainerController
|
||||
int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
|
||||
WindowManagerService service) {
|
||||
super(listener, service);
|
||||
mHandler = new Handler(service.mH.getLooper());
|
||||
mToken = token;
|
||||
synchronized(mWindowMap) {
|
||||
AppWindowToken atoken = mRoot.getAppWindowToken(mToken.asBinder());
|
||||
|
||||
@@ -18,12 +18,10 @@ package com.android.server.wm;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.view.IApplicationToken;
|
||||
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
@@ -74,6 +72,67 @@ public class AppWindowContainerControllerTests extends WindowTestsBase {
|
||||
controller.removeContainer(sDisplayContent.getDisplayId());
|
||||
// Assert orientation is unspecified to after container is removed.
|
||||
assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, controller.getOrientation());
|
||||
|
||||
// Reset display frozen state
|
||||
sWm.mDisplayFrozen = false;
|
||||
}
|
||||
|
||||
private void assertHasStartingWindow(AppWindowToken atoken) {
|
||||
assertNotNull(atoken.startingSurface);
|
||||
assertNotNull(atoken.startingData);
|
||||
assertNotNull(atoken.startingWindow);
|
||||
}
|
||||
|
||||
private void assertNoStartingWindow(AppWindowToken atoken) {
|
||||
assertNull(atoken.startingSurface);
|
||||
assertNull(atoken.startingWindow);
|
||||
assertNull(atoken.startingData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRemoveStartingWindow() throws Exception {
|
||||
final TestAppWindowContainerController controller = createAppWindowController();
|
||||
controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
|
||||
waitUntilHandlerIdle();
|
||||
final AppWindowToken atoken = controller.getAppWindowToken();
|
||||
assertHasStartingWindow(atoken);
|
||||
controller.removeStartingWindow();
|
||||
waitUntilHandlerIdle();
|
||||
assertNoStartingWindow(atoken);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransferStartingWindow() throws Exception {
|
||||
final TestAppWindowContainerController controller1 = createAppWindowController();
|
||||
final TestAppWindowContainerController controller2 = createAppWindowController();
|
||||
controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
|
||||
waitUntilHandlerIdle();
|
||||
controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
|
||||
true, true, false);
|
||||
waitUntilHandlerIdle();
|
||||
assertNoStartingWindow(controller1.getAppWindowToken());
|
||||
assertHasStartingWindow(controller2.getAppWindowToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransferStartingWindowWhileCreating() throws Exception {
|
||||
final TestAppWindowContainerController controller1 = createAppWindowController();
|
||||
final TestAppWindowContainerController controller2 = createAppWindowController();
|
||||
sPolicy.setRunnableWhenAddingSplashScreen(() -> {
|
||||
|
||||
// Surprise, ...! Transfer window in the middle of the creation flow.
|
||||
controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
|
||||
true, true, false);
|
||||
});
|
||||
controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
|
||||
waitUntilHandlerIdle();
|
||||
assertNoStartingWindow(controller1.getAppWindowToken());
|
||||
assertHasStartingWindow(controller2.getAppWindowToken());
|
||||
}
|
||||
|
||||
private TestAppWindowContainerController createAppWindowController() {
|
||||
|
||||
@@ -24,6 +24,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
|
||||
@@ -74,6 +75,7 @@ import android.view.Display;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManagerGlobal;
|
||||
import android.view.WindowManagerPolicy;
|
||||
import android.view.animation.Animation;
|
||||
import android.os.PowerManagerInternal;
|
||||
@@ -92,6 +94,8 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
|
||||
|
||||
int rotationToReport = 0;
|
||||
|
||||
private Runnable mRunnableWhenAddingSplashScreen;
|
||||
|
||||
static synchronized WindowManagerService getWindowManagerService(Context context) {
|
||||
if (sWm == null) {
|
||||
// We only want to do this once for the test process as we don't want WM to try to
|
||||
@@ -318,11 +322,36 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a runnable to run when adding a splash screen which gets executed after the window has
|
||||
* been added but before returning the surface.
|
||||
*/
|
||||
void setRunnableWhenAddingSplashScreen(Runnable r) {
|
||||
mRunnableWhenAddingSplashScreen = r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
|
||||
CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
|
||||
int logo, int windowFlags, Configuration overrideConfig, int displayId) {
|
||||
return null;
|
||||
final com.android.server.wm.WindowState window;
|
||||
final AppWindowToken atoken;
|
||||
synchronized (sWm.mWindowMap) {
|
||||
atoken = WindowTestsBase.sDisplayContent.getAppWindowToken(appToken);
|
||||
window = WindowTestsBase.createWindow(null, TYPE_APPLICATION_STARTING, atoken,
|
||||
"Starting window");
|
||||
atoken.startingWindow = window;
|
||||
}
|
||||
if (mRunnableWhenAddingSplashScreen != null) {
|
||||
mRunnableWhenAddingSplashScreen.run();
|
||||
mRunnableWhenAddingSplashScreen = null;
|
||||
}
|
||||
return () -> {
|
||||
synchronized (sWm.mWindowMap) {
|
||||
atoken.removeChild(window);
|
||||
atoken.startingWindow = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -482,7 +511,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
|
||||
|
||||
@Override
|
||||
public boolean isScreenOn() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -45,20 +45,18 @@ import org.mockito.invocation.InvocationOnMock;
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class UnknownAppVisibilityControllerTest {
|
||||
public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
|
||||
|
||||
private WindowManagerService mWm;
|
||||
private @Mock ActivityManagerInternal mAm;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
super.setUp();
|
||||
final Context context = InstrumentationRegistry.getTargetContext();
|
||||
LocalServices.addService(ActivityManagerInternal.class, mAm);
|
||||
doAnswer((InvocationOnMock invocationOnMock) -> {
|
||||
invocationOnMock.getArgumentAt(0, Runnable.class).run();
|
||||
return null;
|
||||
}).when(mAm).notifyKeyguardFlagsChanged(any());
|
||||
}).when(sMockAm).notifyKeyguardFlagsChanged(any());
|
||||
mWm = TestWindowManagerPolicy.getWindowManagerService(context);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,15 +16,17 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import android.app.ActivityManagerInternal;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Binder;
|
||||
import android.view.IApplicationToken;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.TaskSnapshot;
|
||||
import android.content.Context;
|
||||
import android.os.IBinder;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
@@ -50,13 +52,17 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
|
||||
import static com.android.server.wm.WindowContainer.POSITION_TOP;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import com.android.server.AttributeCache;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
/**
|
||||
* Common base class for window manager unit test classes.
|
||||
*/
|
||||
class WindowTestsBase {
|
||||
static WindowManagerService sWm = null;
|
||||
private final IWindow mIWindow = new TestIWindow();
|
||||
private final Session mMockSession = mock(Session.class);
|
||||
static TestWindowManagerPolicy sPolicy = null;
|
||||
private final static IWindow sIWindow = new TestIWindow();
|
||||
private final static Session sMockSession = mock(Session.class);
|
||||
static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
|
||||
private static int sNextTaskId = 0;
|
||||
|
||||
@@ -72,19 +78,27 @@ class WindowTestsBase {
|
||||
static WindowState sAppWindow;
|
||||
static WindowState sChildAppWindowAbove;
|
||||
static WindowState sChildAppWindowBelow;
|
||||
static @Mock ActivityManagerInternal sMockAm;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
if (sOneTimeSetupDone) {
|
||||
Mockito.reset(sMockAm);
|
||||
return;
|
||||
}
|
||||
sOneTimeSetupDone = true;
|
||||
MockitoAnnotations.initMocks(this);
|
||||
final Context context = InstrumentationRegistry.getTargetContext();
|
||||
LocalServices.addService(ActivityManagerInternal.class, sMockAm);
|
||||
AttributeCache.init(context);
|
||||
sWm = TestWindowManagerPolicy.getWindowManagerService(context);
|
||||
sPolicy = (TestWindowManagerPolicy) sWm.mPolicy;
|
||||
sLayersController = new WindowLayersController(sWm);
|
||||
sDisplayContent = new DisplayContent(context.getDisplay(), sWm, sLayersController,
|
||||
new WallpaperController(sWm));
|
||||
sWm.mRoot.addChild(sDisplayContent, 0);
|
||||
sWm.mDisplayEnabled = true;
|
||||
sWm.mDisplayReady = true;
|
||||
|
||||
// Set-up some common windows.
|
||||
sWallpaperWindow = createWindow(null, TYPE_WALLPAPER, sDisplayContent, "wallpaperWindow");
|
||||
@@ -108,7 +122,14 @@ class WindowTestsBase {
|
||||
Assert.assertTrue("Excepted " + first + " to be greater than " + second, first > second);
|
||||
}
|
||||
|
||||
private WindowToken createWindowToken(DisplayContent dc, int type) {
|
||||
/**
|
||||
* Waits until the main handler for WM has processed all messages.
|
||||
*/
|
||||
void waitUntilHandlerIdle() {
|
||||
sWm.mH.runWithScissors(() -> { }, 0);
|
||||
}
|
||||
|
||||
private static WindowToken createWindowToken(DisplayContent dc, int type) {
|
||||
if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
|
||||
return new TestWindowToken(type, dc);
|
||||
}
|
||||
@@ -120,7 +141,7 @@ class WindowTestsBase {
|
||||
return token;
|
||||
}
|
||||
|
||||
WindowState createWindow(WindowState parent, int type, String name) {
|
||||
static WindowState createWindow(WindowState parent, int type, String name) {
|
||||
return (parent == null)
|
||||
? createWindow(parent, type, sDisplayContent, name)
|
||||
: createWindow(parent, type, parent.mToken, name);
|
||||
@@ -132,16 +153,16 @@ class WindowTestsBase {
|
||||
return createWindow(null, type, token, name);
|
||||
}
|
||||
|
||||
WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name) {
|
||||
static WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name) {
|
||||
final WindowToken token = createWindowToken(dc, type);
|
||||
return createWindow(parent, type, token, name);
|
||||
}
|
||||
|
||||
WindowState createWindow(WindowState parent, int type, WindowToken token, String name) {
|
||||
static WindowState createWindow(WindowState parent, int type, WindowToken token, String name) {
|
||||
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
|
||||
attrs.setTitle(name);
|
||||
|
||||
final WindowState w = new WindowState(sWm, mMockSession, mIWindow, token, parent, OP_NONE,
|
||||
final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE,
|
||||
0, attrs, 0, 0);
|
||||
// TODO: Probably better to make this call in the WindowState ctor to avoid errors with
|
||||
// adding it to the token...
|
||||
@@ -150,14 +171,14 @@ class WindowTestsBase {
|
||||
}
|
||||
|
||||
/** Creates a {@link TaskStack} and adds it to the specified {@link DisplayContent}. */
|
||||
TaskStack createTaskStackOnDisplay(DisplayContent dc) {
|
||||
static TaskStack createTaskStackOnDisplay(DisplayContent dc) {
|
||||
final int stackId = sNextStackId++;
|
||||
dc.addStackToDisplay(stackId, true);
|
||||
return sWm.mStackIdToStack.get(stackId);
|
||||
}
|
||||
|
||||
/**Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
|
||||
Task createTaskInStack(TaskStack stack, int userId) {
|
||||
static Task createTaskInStack(TaskStack stack, int userId) {
|
||||
final Task newTask = new Task(sNextTaskId++, stack, userId, sWm, null, EMPTY, false, 0,
|
||||
false, null);
|
||||
stack.addTask(newTask, POSITION_TOP);
|
||||
@@ -165,7 +186,7 @@ class WindowTestsBase {
|
||||
}
|
||||
|
||||
/* Used so we can gain access to some protected members of the {@link WindowToken} class */
|
||||
class TestWindowToken extends WindowToken {
|
||||
static class TestWindowToken extends WindowToken {
|
||||
|
||||
TestWindowToken(int type, DisplayContent dc) {
|
||||
this(type, dc, false /* persistOnEmpty */);
|
||||
@@ -185,7 +206,7 @@ class WindowTestsBase {
|
||||
}
|
||||
|
||||
/** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
|
||||
class TestAppWindowToken extends AppWindowToken {
|
||||
static class TestAppWindowToken extends AppWindowToken {
|
||||
|
||||
TestAppWindowToken(DisplayContent dc) {
|
||||
super(sWm, null, false, dc);
|
||||
@@ -279,6 +300,10 @@ class WindowTestsBase {
|
||||
0 /* inputDispatchingTimeoutNanos */, sWm);
|
||||
mToken = token;
|
||||
}
|
||||
|
||||
AppWindowToken getAppWindowToken() {
|
||||
return (AppWindowToken) sDisplayContent.getWindowToken(mToken.asBinder());
|
||||
}
|
||||
}
|
||||
|
||||
class TestIApplicationToken implements IApplicationToken {
|
||||
@@ -295,7 +320,7 @@ class WindowTestsBase {
|
||||
boolean resizeReported;
|
||||
|
||||
TestWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
|
||||
super(sWm, mMockSession, mIWindow, token, null, OP_NONE, 0, attrs, 0, 0);
|
||||
super(sWm, sMockSession, sIWindow, token, null, OP_NONE, 0, attrs, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user