WindowFrameTests.java revision 16a4e3cbf7068504e4628ed6e81e7700a6f8edbc
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.Before; 20import org.junit.Test; 21import org.junit.runner.RunWith; 22 23import android.content.Context; 24import android.graphics.Rect; 25import android.os.Binder; 26import android.platform.test.annotations.Presubmit; 27import android.support.test.InstrumentationRegistry; 28import android.support.test.filters.SmallTest; 29import android.support.test.runner.AndroidJUnit4; 30import android.view.Gravity; 31import android.view.IWindow; 32import android.view.WindowManager; 33 34import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 35import static android.view.WindowManager.LayoutParams.FLAG_SCALED; 36import static android.view.WindowManager.LayoutParams.FILL_PARENT; 37import static org.junit.Assert.assertEquals; 38 39/** 40 * Tests for the {@link WindowState#computeFrameLw} method and other window frame machinery. 41 * 42 * Build/Install/Run: bit FrameworksServicesTests:com.android.server.wm.WindowFrameTests 43 */ 44@SmallTest 45@Presubmit 46@RunWith(AndroidJUnit4.class) 47public class WindowFrameTests { 48 49 private static WindowManagerService sWm = null; 50 private WindowToken mWindowToken; 51 private final IWindow mIWindow = new TestIWindow(); 52 53 class WindowStateWithTask extends WindowState { 54 final Task mTask; 55 WindowStateWithTask(WindowManager.LayoutParams attrs, Task t) { 56 super(sWm, null, mIWindow, mWindowToken, null, 0, 0, attrs, 0, 0); 57 mTask = t; 58 } 59 60 @Override 61 Task getTask() { 62 return mTask; 63 } 64 }; 65 66 class TaskWithBounds extends Task { 67 final Rect mBounds; 68 TaskWithBounds(Rect bounds) { 69 super(0, mStubStack, 0, sWm, null, null, false); 70 mBounds = bounds; 71 } 72 @Override 73 void getBounds(Rect outBounds) { 74 outBounds.set(mBounds); 75 } 76 @Override 77 void getTempInsetBounds(Rect outBounds) { 78 outBounds.setEmpty(); 79 } 80 @Override 81 boolean isFullscreen() { 82 return true; 83 } 84 } 85 86 TaskStack mStubStack; 87 88 @Before 89 public void setUp() throws Exception { 90 final Context context = InstrumentationRegistry.getTargetContext(); 91 sWm = TestWindowManagerPolicy.getWindowManagerService(context); 92 mWindowToken = new WindowToken(sWm, new Binder(), 0, false, 93 sWm.getDefaultDisplayContentLocked()); 94 mStubStack = new TaskStack(sWm, 0); 95 } 96 97 public void assertRect(Rect rect, int left, int top, int right, int bottom) { 98 assertEquals(left, rect.left); 99 assertEquals(top, rect.top); 100 assertEquals(right, rect.right); 101 assertEquals(bottom, rect.bottom); 102 } 103 104 @Test 105 public void testLayoutInFullscreenTaskNoInsets() throws Exception { 106 Task task = new TaskWithBounds(null); // fullscreen task doesn't use bounds for computeFrame 107 WindowState w = createWindow(task, FILL_PARENT, FILL_PARENT); 108 w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; 109 110 // With no insets or system decor all the frames incoming from PhoneWindowManager 111 // are identical. 112 final Rect pf = new Rect(0, 0, 1000, 1000); 113 114 // Here the window has FILL_PARENT, FILL_PARENT 115 // so we expect it to fill the entire available frame. 116 w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf); 117 assertRect(w.mFrame, 0, 0, 1000, 1000); 118 119 // It can select various widths and heights within the bounds. 120 // Strangely the window attribute width is ignored for normal windows 121 // and we use mRequestedWidth/mRequestedHeight 122 w.mAttrs.width = 300; 123 w.mAttrs.height = 300; 124 w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf); 125 // Explicit width and height without requested width/height 126 // gets us nothing. 127 assertRect(w.mFrame, 0, 0, 0, 0); 128 129 w.mRequestedWidth = 300; 130 w.mRequestedHeight = 300; 131 w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf); 132 // With requestedWidth/Height we can freely choose our size within the 133 // parent bounds. 134 assertRect(w.mFrame, 0, 0, 300, 300); 135 136 // With FLAG_SCALED though, requestedWidth/height is used to control 137 // the unscaled surface size, and mAttrs.width/height becomes the 138 // layout controller. 139 w.mAttrs.flags = WindowManager.LayoutParams.FLAG_SCALED; 140 w.mRequestedHeight = -1; 141 w.mRequestedWidth = -1; 142 w.mAttrs.width = 100; 143 w.mAttrs.height = 100; 144 w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf); 145 assertRect(w.mFrame, 0, 0, 100, 100); 146 w.mAttrs.flags = 0; 147 148 // But sizes too large will be clipped to the containing frame 149 w.mRequestedWidth = 1200; 150 w.mRequestedHeight = 1200; 151 w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf); 152 assertRect(w.mFrame, 0, 0, 1000, 1000); 153 154 // Before they are clipped though windows will be shifted 155 w.mAttrs.x = 300; 156 w.mAttrs.y = 300; 157 w.mRequestedWidth = 1000; 158 w.mRequestedHeight = 1000; 159 w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf); 160 assertRect(w.mFrame, 0, 0, 1000, 1000); 161 162 // If there is room to move around in the parent frame the window will be shifted according 163 // to gravity. 164 w.mAttrs.x = 0; 165 w.mAttrs.y = 0; 166 w.mRequestedWidth = 300; 167 w.mRequestedHeight = 300; 168 w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP; 169 w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf); 170 assertRect(w.mFrame, 700, 0, 1000, 300); 171 w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM; 172 w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf); 173 assertRect(w.mFrame, 700, 700, 1000, 1000); 174 // Window specified x and y are interpreted as offsets in the opposite 175 // direction of gravity 176 w.mAttrs.x = 100; 177 w.mAttrs.y = 100; 178 w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf); 179 assertRect(w.mFrame, 600, 600, 900, 900); 180 } 181 182 private WindowState createWindow(Task task, int width, int height) { 183 final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION); 184 attrs.width = width; 185 attrs.height = height; 186 187 return new WindowStateWithTask(attrs, task); 188 } 189} 190