blob: 23a097eb0c7cea4ff7a465f12c69aed82bfed524 [file] [log] [blame]
/*
* Copyright (C) 2016 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.os.Process.INVALID_UID;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import android.content.res.Configuration;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Tests for the {@link WindowToken} class.
*
* Build/Install/Run:
* atest WmTests:WindowTokenTests
*/
@SmallTest
@Presubmit
@RunWith(WindowTestRunner.class)
public class WindowTokenTests extends WindowTestsBase {
@Test
public void testAddWindow() {
final WindowTestUtils.TestWindowToken token =
WindowTestUtils.createTestWindowToken(0, mDisplayContent);
assertEquals(0, token.getWindowsCount());
final WindowState window1 = createWindow(null, TYPE_APPLICATION, token, "window1");
final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token, "window11");
final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token, "window12");
final WindowState window2 = createWindow(null, TYPE_APPLICATION, token, "window2");
final WindowState window3 = createWindow(null, TYPE_APPLICATION, token, "window3");
token.addWindow(window1);
// NOTE: Child windows will not be added to the token as window containers can only
// contain/reference their direct children.
token.addWindow(window11);
token.addWindow(window12);
token.addWindow(window2);
token.addWindow(window3);
// Should not contain the child windows that were added above.
assertEquals(3, token.getWindowsCount());
assertTrue(token.hasWindow(window1));
assertFalse(token.hasWindow(window11));
assertFalse(token.hasWindow(window12));
assertTrue(token.hasWindow(window2));
assertTrue(token.hasWindow(window3));
}
@Test
public void testChildRemoval() {
final DisplayContent dc = mDisplayContent;
final WindowTestUtils.TestWindowToken token = WindowTestUtils.createTestWindowToken(0, dc);
assertEquals(token, dc.getWindowToken(token.token));
final WindowState window1 = createWindow(null, TYPE_APPLICATION, token, "window1");
final WindowState window2 = createWindow(null, TYPE_APPLICATION, token, "window2");
window2.removeImmediately();
// The token should still be mapped in the display content since it still has a child.
assertEquals(token, dc.getWindowToken(token.token));
window1.removeImmediately();
// The token should have been removed from the display content since it no longer has a
// child.
assertEquals(null, dc.getWindowToken(token.token));
}
/**
* Test that a window token isn't orphaned by the system when it is requested to be removed.
* Tokens should only be removed from the system when all their windows are gone.
*/
@Test
public void testTokenRemovalProcess() {
final WindowTestUtils.TestWindowToken token = WindowTestUtils.createTestWindowToken(
TYPE_TOAST, mDisplayContent, true /* persistOnEmpty */);
// Verify that the token is on the display
assertNotNull(mDisplayContent.getWindowToken(token.token));
final WindowState window1 = createWindow(null, TYPE_TOAST, token, "window1");
final WindowState window2 = createWindow(null, TYPE_TOAST, token, "window2");
mDisplayContent.removeWindowToken(token.token);
// Verify that the token is no longer mapped on the display
assertNull(mDisplayContent.getWindowToken(token.token));
// Verify that the token is still attached to its parent
assertNotNull(token.getParent());
// Verify that the token windows are still around.
assertEquals(2, token.getWindowsCount());
window1.removeImmediately();
// Verify that the token is still attached to its parent
assertNotNull(token.getParent());
// Verify that the other token window is still around.
assertEquals(1, token.getWindowsCount());
window2.removeImmediately();
// Verify that the token is no-longer attached to its parent
assertNull(token.getParent());
// Verify that the token windows are no longer attached to it.
assertEquals(0, token.getWindowsCount());
}
@Test
public void testFinishFixedRotationTransform() {
final WindowToken appToken = mAppWindow.mToken;
final WindowToken wallpaperToken = mWallpaperWindow.mToken;
final Configuration config = new Configuration(mDisplayContent.getConfiguration());
final int originalRotation = config.windowConfiguration.getRotation();
final int targetRotation = (originalRotation + 1) % 4;
config.windowConfiguration.setRotation(targetRotation);
appToken.applyFixedRotationTransform(mDisplayInfo, mDisplayContent.mDisplayFrames, config);
wallpaperToken.linkFixedRotationTransform(appToken);
// The window tokens should apply the rotation by the transformation.
assertEquals(targetRotation, appToken.getWindowConfiguration().getRotation());
assertEquals(targetRotation, wallpaperToken.getWindowConfiguration().getRotation());
// The display doesn't rotate, the transformation will be canceled.
mAppWindow.mToken.finishFixedRotationTransform();
// The window tokens should restore to the original rotation.
assertEquals(originalRotation, appToken.getWindowConfiguration().getRotation());
assertEquals(originalRotation, wallpaperToken.getWindowConfiguration().getRotation());
}
/**
* Test that {@link WindowToken} constructor parameters is set with expectation.
*/
@Test
public void testWindowTokenConstructorSanity() {
WindowToken token = new WindowToken(mDisplayContent.mWmService, mock(IBinder.class),
TYPE_TOAST, true /* persistOnEmpty */, mDisplayContent,
true /* ownerCanManageAppTokens */);
assertFalse(token.mRoundedCornerOverlay);
assertFalse(token.mFromClientToken);
token = new WindowToken(mDisplayContent.mWmService, mock(IBinder.class), TYPE_TOAST,
true /* persistOnEmpty */, mDisplayContent, true /* ownerCanManageAppTokens */,
true /* roundedCornerOverlay */);
assertTrue(token.mRoundedCornerOverlay);
assertFalse(token.mFromClientToken);
token = new WindowToken(mDisplayContent.mWmService, mock(IBinder.class), TYPE_TOAST,
true /* persistOnEmpty */, mDisplayContent, true /* ownerCanManageAppTokens */,
INVALID_UID, true /* roundedCornerOverlay */, true /* fromClientToken */);
assertTrue(token.mRoundedCornerOverlay);
assertTrue(token.mFromClientToken);
}
/**
* Test that {@link android.view.SurfaceControl} should not be created for the
* {@link WindowToken} which was created for {@link android.app.WindowContext} initially, the
* surface should be create after addWindow for this token.
*/
@Test
public void testSurfaceCreatedForWindowToken() {
final WindowToken fromClientToken = new WindowToken(mDisplayContent.mWmService,
mock(IBinder.class), TYPE_APPLICATION_OVERLAY, true /* persistOnEmpty */,
mDisplayContent, true /* ownerCanManageAppTokens */, INVALID_UID,
true /* roundedCornerOverlay */, true /* fromClientToken */);
assertNull(fromClientToken.mSurfaceControl);
createWindow(null, TYPE_APPLICATION_OVERLAY, fromClientToken, "window");
assertNotNull(fromClientToken.mSurfaceControl);
final WindowToken nonClientToken = new WindowToken(mDisplayContent.mWmService,
mock(IBinder.class), TYPE_TOAST, true /* persistOnEmpty */, mDisplayContent,
true /* ownerCanManageAppTokens */, INVALID_UID, true /* roundedCornerOverlay */,
false /* fromClientToken */);
assertNotNull(nonClientToken.mSurfaceControl);
}
}