1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package com.android.server.wm; 18 19import org.junit.Test; 20import org.junit.runner.RunWith; 21 22import android.platform.test.annotations.Presubmit; 23import android.support.test.filters.SmallTest; 24import android.support.test.runner.AndroidJUnit4; 25import android.view.Surface; 26import android.view.WindowManager; 27 28import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; 29import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; 30import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; 31import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; 32import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; 33import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; 34import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 35import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 36import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 37import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 38import static org.junit.Assert.assertEquals; 39import static org.junit.Assert.assertFalse; 40import static org.junit.Assert.assertNull; 41import static org.junit.Assert.assertTrue; 42/** 43 * Tests for the {@link AppWindowToken} class. 44 * 45 * Build/Install/Run: 46 * bit FrameworksServicesTests:com.android.server.wm.AppWindowTokenTests 47 */ 48@SmallTest 49@Presubmit 50@RunWith(AndroidJUnit4.class) 51public class AppWindowTokenTests extends WindowTestsBase { 52 53 @Test 54 public void testAddWindow_Order() throws Exception { 55 final WindowTestUtils.TestAppWindowToken token = 56 new WindowTestUtils.TestAppWindowToken(mDisplayContent); 57 58 assertEquals(0, token.getWindowsCount()); 59 60 final WindowState win1 = createWindow(null, TYPE_APPLICATION, token, "win1"); 61 final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, token, 62 "startingWin"); 63 final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, token, "baseWin"); 64 final WindowState win4 = createWindow(null, TYPE_APPLICATION, token, "win4"); 65 66 // Should not contain the windows that were added above. 67 assertEquals(4, token.getWindowsCount()); 68 assertTrue(token.hasWindow(win1)); 69 assertTrue(token.hasWindow(startingWin)); 70 assertTrue(token.hasWindow(baseWin)); 71 assertTrue(token.hasWindow(win4)); 72 73 // The starting window should be on-top of all other windows. 74 assertEquals(startingWin, token.getLastChild()); 75 76 // The base application window should be below all other windows. 77 assertEquals(baseWin, token.getFirstChild()); 78 token.removeImmediately(); 79 } 80 81 @Test 82 public void testFindMainWindow() throws Exception { 83 final WindowTestUtils.TestAppWindowToken token = 84 new WindowTestUtils.TestAppWindowToken(mDisplayContent); 85 86 assertNull(token.findMainWindow()); 87 88 final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, token, "window1"); 89 final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token, "window11"); 90 final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token, "window12"); 91 assertEquals(window1, token.findMainWindow()); 92 window1.mAnimatingExit = true; 93 assertEquals(window1, token.findMainWindow()); 94 final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, token, "window2"); 95 assertEquals(window2, token.findMainWindow()); 96 token.removeImmediately(); 97 } 98 99 @Test 100 public void testLandscapeSeascapeRotationByApp() throws Exception { 101 // Some plumbing to get the service ready for rotation updates. 102 sWm.mDisplayReady = true; 103 sWm.mDisplayEnabled = true; 104 105 // Create an app window with token on a display. 106 final TaskStack stack = createTaskStackOnDisplay(mDisplayContent); 107 final Task task = createTaskInStack(stack, 0 /* userId */); 108 final WindowTestUtils.TestAppWindowToken appWindowToken = 109 new WindowTestUtils.TestAppWindowToken(mDisplayContent); 110 task.addChild(appWindowToken, 0); 111 final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams( 112 TYPE_BASE_APPLICATION); 113 attrs.setTitle("AppWindow"); 114 final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, appWindowToken); 115 appWindowToken.addWindow(appWindow); 116 117 // Set initial orientation and update. 118 appWindowToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE); 119 sWm.updateOrientationFromAppTokens(mDisplayContent.getOverrideConfiguration(), null, 120 mDisplayContent.getDisplayId()); 121 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mDisplayContent.getLastOrientation()); 122 appWindow.resizeReported = false; 123 124 // Update the orientation to perform 180 degree rotation and check that resize was reported. 125 appWindowToken.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE); 126 sWm.updateOrientationFromAppTokens(mDisplayContent.getOverrideConfiguration(), null, 127 mDisplayContent.getDisplayId()); 128 sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */); 129 assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, mDisplayContent.getLastOrientation()); 130 assertTrue(appWindow.resizeReported); 131 appWindow.removeImmediately(); 132 } 133 134 @Test 135 public void testLandscapeSeascapeRotationByPolicy() throws Exception { 136 // Some plumbing to get the service ready for rotation updates. 137 sWm.mDisplayReady = true; 138 sWm.mDisplayEnabled = true; 139 140 // Create an app window with token on a display. 141 final DisplayContent defaultDisplayContent = sWm.getDefaultDisplayContentLocked(); 142 final TaskStack stack = createTaskStackOnDisplay(defaultDisplayContent); 143 final Task task = createTaskInStack(stack, 0 /* userId */); 144 final WindowTestUtils.TestAppWindowToken appWindowToken = 145 new WindowTestUtils.TestAppWindowToken(defaultDisplayContent); 146 task.addChild(appWindowToken, 0); 147 final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams( 148 TYPE_BASE_APPLICATION); 149 attrs.setTitle("AppWindow"); 150 final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, appWindowToken); 151 appWindowToken.addWindow(appWindow); 152 153 // Set initial orientation and update. 154 performRotation(Surface.ROTATION_90); 155 appWindow.resizeReported = false; 156 157 // Update the rotation to perform 180 degree rotation and check that resize was reported. 158 performRotation(Surface.ROTATION_270); 159 assertTrue(appWindow.resizeReported); 160 appWindow.removeImmediately(); 161 } 162 163 private void performRotation(int rotationToReport) { 164 ((TestWindowManagerPolicy) sWm.mPolicy).rotationToReport = rotationToReport; 165 sWm.updateRotation(false, false); 166 // Simulate animator finishing orientation change 167 sWm.mRoot.mOrientationChangeComplete = true; 168 sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */); 169 } 170 171 @Test 172 public void testGetOrientation() throws Exception { 173 final WindowTestUtils.TestAppWindowToken token = 174 new WindowTestUtils.TestAppWindowToken(mDisplayContent); 175 token.setOrientation(SCREEN_ORIENTATION_LANDSCAPE); 176 177 token.setFillsParent(false); 178 // Can specify orientation if app doesn't fill parent. Allowed for SDK <= 25. 179 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, token.getOrientation()); 180 181 token.setFillsParent(true); 182 token.hidden = true; 183 token.sendingToBottom = true; 184 // Can not specify orientation if app isn't visible even though it fills parent. 185 assertEquals(SCREEN_ORIENTATION_UNSET, token.getOrientation()); 186 // Can specify orientation if the current orientation candidate is orientation behind. 187 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, token.getOrientation(SCREEN_ORIENTATION_BEHIND)); 188 } 189 190 @Test 191 public void testKeyguardFlagsDuringRelaunch() throws Exception { 192 final WindowTestUtils.TestAppWindowToken token = 193 new WindowTestUtils.TestAppWindowToken(mDisplayContent); 194 final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams( 195 TYPE_BASE_APPLICATION); 196 attrs.flags |= FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD; 197 attrs.setTitle("AppWindow"); 198 final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, token); 199 200 // Add window with show when locked flag 201 token.addWindow(appWindow); 202 assertTrue(token.containsShowWhenLockedWindow() && token.containsDismissKeyguardWindow()); 203 204 // Start relaunching 205 token.startRelaunching(); 206 assertTrue(token.containsShowWhenLockedWindow() && token.containsDismissKeyguardWindow()); 207 208 // Remove window and make sure that we still report back flag 209 token.removeChild(appWindow); 210 assertTrue(token.containsShowWhenLockedWindow() && token.containsDismissKeyguardWindow()); 211 212 // Finish relaunching and ensure flag is now not reported 213 token.finishRelaunching(); 214 assertFalse(token.containsShowWhenLockedWindow() || token.containsDismissKeyguardWindow()); 215 } 216} 217