Home | History | Annotate | Download | only in wm
      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 
     17 package com.android.server.wm;
     18 
     19 import org.junit.Test;
     20 import org.junit.runner.RunWith;
     21 
     22 import android.platform.test.annotations.Presubmit;
     23 import android.support.test.filters.FlakyTest;
     24 import android.support.test.filters.SmallTest;
     25 import android.support.test.runner.AndroidJUnit4;
     26 import android.view.Surface;
     27 import android.view.WindowManager;
     28 
     29 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
     30 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
     31 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
     32 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
     33 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
     34 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
     35 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
     36 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
     37 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
     38 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
     39 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
     40 import static android.view.WindowManager.TRANSIT_UNSET;
     41 import static org.junit.Assert.assertEquals;
     42 import static org.junit.Assert.assertFalse;
     43 import static org.junit.Assert.assertNull;
     44 import static org.junit.Assert.assertTrue;
     45 /**
     46  * Tests for the {@link AppWindowToken} class.
     47  *
     48  * Build/Install/Run:
     49  *  atest FrameworksServicesTests:com.android.server.wm.AppWindowTokenTests
     50  */
     51 @SmallTest
     52 // TODO: b/68267650
     53 // @Presubmit
     54 @RunWith(AndroidJUnit4.class)
     55 public class AppWindowTokenTests extends WindowTestsBase {
     56 
     57     TaskStack mStack;
     58     Task mTask;
     59     WindowTestUtils.TestAppWindowToken mToken;
     60 
     61     @Override
     62     public void setUp() throws Exception {
     63         super.setUp();
     64 
     65         mStack = createTaskStackOnDisplay(mDisplayContent);
     66         mTask = createTaskInStack(mStack, 0 /* userId */);
     67         mToken = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
     68 
     69         mTask.addChild(mToken, 0);
     70     }
     71 
     72     @Test
     73     @Presubmit
     74     public void testAddWindow_Order() throws Exception {
     75         assertEquals(0, mToken.getWindowsCount());
     76 
     77         final WindowState win1 = createWindow(null, TYPE_APPLICATION, mToken, "win1");
     78         final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, mToken,
     79                 "startingWin");
     80         final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, mToken, "baseWin");
     81         final WindowState win4 = createWindow(null, TYPE_APPLICATION, mToken, "win4");
     82 
     83         // Should not contain the windows that were added above.
     84         assertEquals(4, mToken.getWindowsCount());
     85         assertTrue(mToken.hasWindow(win1));
     86         assertTrue(mToken.hasWindow(startingWin));
     87         assertTrue(mToken.hasWindow(baseWin));
     88         assertTrue(mToken.hasWindow(win4));
     89 
     90         // The starting window should be on-top of all other windows.
     91         assertEquals(startingWin, mToken.getLastChild());
     92 
     93         // The base application window should be below all other windows.
     94         assertEquals(baseWin, mToken.getFirstChild());
     95         mToken.removeImmediately();
     96     }
     97 
     98     @Test
     99     @Presubmit
    100     public void testFindMainWindow() throws Exception {
    101         assertNull(mToken.findMainWindow());
    102 
    103         final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, mToken, "window1");
    104         final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, mToken, "window11");
    105         final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, mToken, "window12");
    106         assertEquals(window1, mToken.findMainWindow());
    107         window1.mAnimatingExit = true;
    108         assertEquals(window1, mToken.findMainWindow());
    109         final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, mToken, "window2");
    110         assertEquals(window2, mToken.findMainWindow());
    111         mToken.removeImmediately();
    112     }
    113 
    114     @Test
    115     @Presubmit
    116     public void testGetTopFullscreenWindow() throws Exception {
    117         assertNull(mToken.getTopFullscreenWindow());
    118 
    119         final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, mToken, "window1");
    120         final WindowState window11 = createWindow(null, TYPE_APPLICATION, mToken, "window11");
    121         final WindowState window12 = createWindow(null, TYPE_APPLICATION, mToken, "window12");
    122         assertEquals(window12, mToken.getTopFullscreenWindow());
    123         window12.mAttrs.width = 500;
    124         assertEquals(window11, mToken.getTopFullscreenWindow());
    125         window11.mAttrs.width = 500;
    126         assertEquals(window1, mToken.getTopFullscreenWindow());
    127         mToken.removeImmediately();
    128     }
    129 
    130     @Test
    131     public void testLandscapeSeascapeRotationByApp() throws Exception {
    132         // Some plumbing to get the service ready for rotation updates.
    133         sWm.mDisplayReady = true;
    134         sWm.mDisplayEnabled = true;
    135 
    136         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
    137                 TYPE_BASE_APPLICATION);
    138         attrs.setTitle("AppWindow");
    139         final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mToken);
    140         mToken.addWindow(appWindow);
    141 
    142         // Set initial orientation and update.
    143         mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
    144         sWm.updateOrientationFromAppTokens(mDisplayContent.getOverrideConfiguration(), null,
    145                 mDisplayContent.getDisplayId());
    146         assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mDisplayContent.getLastOrientation());
    147         appWindow.resizeReported = false;
    148 
    149         // Update the orientation to perform 180 degree rotation and check that resize was reported.
    150         mToken.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
    151         sWm.updateOrientationFromAppTokens(mDisplayContent.getOverrideConfiguration(), null,
    152                 mDisplayContent.getDisplayId());
    153         sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
    154         assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, mDisplayContent.getLastOrientation());
    155         assertTrue(appWindow.resizeReported);
    156         appWindow.removeImmediately();
    157     }
    158 
    159     @Test
    160     public void testLandscapeSeascapeRotationByPolicy() throws Exception {
    161         // Some plumbing to get the service ready for rotation updates.
    162         sWm.mDisplayReady = true;
    163         sWm.mDisplayEnabled = true;
    164 
    165         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
    166                 TYPE_BASE_APPLICATION);
    167         attrs.setTitle("AppWindow");
    168         final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mToken);
    169         mToken.addWindow(appWindow);
    170 
    171         // Set initial orientation and update.
    172         performRotation(Surface.ROTATION_90);
    173         appWindow.resizeReported = false;
    174 
    175         // Update the rotation to perform 180 degree rotation and check that resize was reported.
    176         performRotation(Surface.ROTATION_270);
    177         assertTrue(appWindow.resizeReported);
    178         appWindow.removeImmediately();
    179     }
    180 
    181     private void performRotation(int rotationToReport) {
    182         ((TestWindowManagerPolicy) sWm.mPolicy).rotationToReport = rotationToReport;
    183         sWm.updateRotation(false, false);
    184         // Simulate animator finishing orientation change
    185         sWm.mRoot.mOrientationChangeComplete = true;
    186         sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
    187     }
    188 
    189     @Test
    190     @Presubmit
    191     public void testGetOrientation() throws Exception {
    192         mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
    193 
    194         mToken.setFillsParent(false);
    195         // Can specify orientation if app doesn't fill parent.
    196         assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mToken.getOrientation());
    197 
    198         mToken.setFillsParent(true);
    199         mToken.setHidden(true);
    200         mToken.sendingToBottom = true;
    201         // Can not specify orientation if app isn't visible even though it fills parent.
    202         assertEquals(SCREEN_ORIENTATION_UNSET, mToken.getOrientation());
    203         // Can specify orientation if the current orientation candidate is orientation behind.
    204         assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mToken.getOrientation(SCREEN_ORIENTATION_BEHIND));
    205     }
    206 
    207     @Test
    208     @Presubmit
    209     public void testKeyguardFlagsDuringRelaunch() throws Exception {
    210         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
    211                 TYPE_BASE_APPLICATION);
    212         attrs.flags |= FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD;
    213         attrs.setTitle("AppWindow");
    214         final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mToken);
    215 
    216         // Add window with show when locked flag
    217         mToken.addWindow(appWindow);
    218         assertTrue(mToken.containsShowWhenLockedWindow() && mToken.containsDismissKeyguardWindow());
    219 
    220         // Start relaunching
    221         mToken.startRelaunching();
    222         assertTrue(mToken.containsShowWhenLockedWindow() && mToken.containsDismissKeyguardWindow());
    223 
    224         // Remove window and make sure that we still report back flag
    225         mToken.removeChild(appWindow);
    226         assertTrue(mToken.containsShowWhenLockedWindow() && mToken.containsDismissKeyguardWindow());
    227 
    228         // Finish relaunching and ensure flag is now not reported
    229         mToken.finishRelaunching();
    230         assertFalse(mToken.containsShowWhenLockedWindow() || mToken.containsDismissKeyguardWindow());
    231     }
    232 
    233     @Test
    234     @FlakyTest(detail = "Promote once confirmed non-flaky")
    235     public void testStuckExitingWindow() throws Exception {
    236         final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
    237                 "closingWindow");
    238         closingWindow.mAnimatingExit = true;
    239         closingWindow.mRemoveOnExit = true;
    240         closingWindow.mAppToken.setVisibility(null, false /* visible */, TRANSIT_UNSET,
    241                 true /* performLayout */, false /* isVoiceInteraction */);
    242 
    243         // We pretended that we were running an exit animation, but that should have been cleared up
    244         // by changing visibility of AppWindowToken
    245         closingWindow.removeIfPossible();
    246         assertTrue(closingWindow.mRemoved);
    247     }
    248 }
    249