1 /* 2 * Copyright (C) 2018 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 static android.view.InsetsSource.ID_IME; 20 import static android.view.WindowInsets.Type.ime; 21 import static android.view.WindowInsets.Type.statusBars; 22 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 23 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 24 25 import static org.junit.Assert.assertEquals; 26 import static org.junit.Assert.assertFalse; 27 import static org.junit.Assert.assertNotNull; 28 import static org.junit.Assert.assertNull; 29 import static org.junit.Assert.assertTrue; 30 31 import android.graphics.Insets; 32 import android.graphics.Rect; 33 import android.platform.test.annotations.Presubmit; 34 import android.view.InsetsSource; 35 36 import androidx.test.filters.SmallTest; 37 38 import org.junit.Before; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 42 @SmallTest 43 @Presubmit 44 @RunWith(WindowTestRunner.class) 45 public class InsetsSourceProviderTest extends WindowTestsBase { 46 47 private InsetsSource mSource = new InsetsSource( 48 InsetsSource.createId(null, 0, statusBars()), statusBars()); 49 private InsetsSourceProvider mProvider; 50 private InsetsSource mImeSource = new InsetsSource(ID_IME, ime()); 51 private InsetsSourceProvider mImeProvider; 52 53 @Before setUp()54 public void setUp() throws Exception { 55 mSource.setVisible(true); 56 mProvider = new InsetsSourceProvider(mSource, 57 mDisplayContent.getInsetsStateController(), mDisplayContent); 58 mImeProvider = new InsetsSourceProvider(mImeSource, 59 mDisplayContent.getInsetsStateController(), mDisplayContent); 60 } 61 62 @Test testPostLayout()63 public void testPostLayout() { 64 final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); 65 statusBar.setBounds(0, 0, 500, 1000); 66 statusBar.getFrame().set(0, 0, 500, 100); 67 statusBar.mHasSurface = true; 68 mProvider.setWindowContainer(statusBar, null, null); 69 mProvider.updateSourceFrame(statusBar.getFrame()); 70 mProvider.onPostLayout(); 71 assertEquals(new Rect(0, 0, 500, 100), mProvider.getSource().getFrame()); 72 assertEquals(Insets.of(0, 100, 0, 0), mProvider.getInsetsHint()); 73 74 // Change the bounds and call onPostLayout. Make sure the insets hint gets updated. 75 statusBar.setBounds(0, 10, 500, 1000); 76 mProvider.onPostLayout(); 77 assertEquals(Insets.of(0, 90, 0, 0), mProvider.getInsetsHint()); 78 } 79 80 @Test testPostLayout_invisible()81 public void testPostLayout_invisible() { 82 final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); 83 statusBar.setBounds(0, 0, 500, 1000); 84 statusBar.getFrame().set(0, 0, 500, 100); 85 mProvider.setWindowContainer(statusBar, null, null); 86 mProvider.updateSourceFrame(statusBar.getFrame()); 87 mProvider.onPostLayout(); 88 assertTrue(mProvider.getSource().getFrame().isEmpty()); 89 assertEquals(Insets.NONE, mProvider.getInsetsHint()); 90 } 91 92 @Test testPostLayout_frameProvider()93 public void testPostLayout_frameProvider() { 94 final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); 95 statusBar.getFrame().set(0, 0, 500, 100); 96 statusBar.mHasSurface = true; 97 mProvider.setWindowContainer(statusBar, 98 (displayFrames, windowState, rect) -> { 99 rect.set(10, 10, 20, 20); 100 return 0; 101 }, null); 102 mProvider.updateSourceFrame(statusBar.getFrame()); 103 mProvider.onPostLayout(); 104 assertEquals(new Rect(10, 10, 20, 20), mProvider.getSource().getFrame()); 105 } 106 107 @Test testUpdateControlForTarget()108 public void testUpdateControlForTarget() { 109 final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); 110 final WindowState target = createWindow(null, TYPE_APPLICATION, "target"); 111 statusBar.getFrame().set(0, 0, 500, 100); 112 113 // We must not have control or control target before we have the insets source window. 114 mProvider.updateControlForTarget(target, true /* force */); 115 assertNull(mProvider.getControl(target)); 116 assertNull(mProvider.getControlTarget()); 117 118 // We can have the control or the control target after we have the insets source window. 119 mProvider.setWindowContainer(statusBar, null, null); 120 mProvider.updateControlForTarget(target, false /* force */); 121 assertNotNull(mProvider.getControl(target)); 122 assertNotNull(mProvider.getControlTarget()); 123 124 // We must not have control or control target while we are performing seamless rotation. 125 // And the control and the control target must not be updated during that. 126 mProvider.startSeamlessRotation(); 127 assertNull(mProvider.getControl(target)); 128 assertNull(mProvider.getControlTarget()); 129 mProvider.updateControlForTarget(target, true /* force */); 130 assertNull(mProvider.getControl(target)); 131 assertNull(mProvider.getControlTarget()); 132 133 // We can have the control and the control target after seamless rotation. 134 mProvider.finishSeamlessRotation(); 135 mProvider.updateControlForTarget(target, false /* force */); 136 assertNotNull(mProvider.getControl(target)); 137 assertNotNull(mProvider.getControlTarget()); 138 139 // We can clear the control and the control target. 140 mProvider.updateControlForTarget(null, false /* force */); 141 assertNull(mProvider.getControl(target)); 142 assertNull(mProvider.getControlTarget()); 143 144 // We must not have control or control target if the insets source window doesn't have a 145 // surface. 146 statusBar.setSurfaceControl(null); 147 mProvider.updateControlForTarget(target, true /* force */); 148 assertNull(mProvider.getControl(target)); 149 assertNull(mProvider.getControlTarget()); 150 } 151 152 @Test testUpdateControlForFakeTarget()153 public void testUpdateControlForFakeTarget() { 154 final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); 155 final WindowState target = createWindow(null, TYPE_APPLICATION, "target"); 156 statusBar.getFrame().set(0, 0, 500, 100); 157 mProvider.setWindowContainer(statusBar, null, null); 158 mProvider.updateFakeControlTarget(target); 159 assertNotNull(mProvider.getControl(target)); 160 assertNull(mProvider.getControl(target).getLeash()); 161 mProvider.updateFakeControlTarget(null); 162 assertNull(mProvider.getControl(target)); 163 } 164 165 @Test testUpdateSourceFrame()166 public void testUpdateSourceFrame() { 167 final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); 168 mProvider.setWindowContainer(statusBar, null, null); 169 statusBar.setBounds(0, 0, 500, 1000); 170 171 mProvider.setServerVisible(true); 172 statusBar.getFrame().set(0, 0, 500, 100); 173 mProvider.updateSourceFrame(statusBar.getFrame()); 174 assertEquals(statusBar.getFrame(), mProvider.getSource().getFrame()); 175 assertEquals(Insets.of(0, 100, 0, 0), mProvider.getInsetsHint()); 176 177 // Only change the source frame but not the visibility. 178 statusBar.getFrame().set(0, 0, 500, 90); 179 mProvider.updateSourceFrame(statusBar.getFrame()); 180 assertEquals(statusBar.getFrame(), mProvider.getSource().getFrame()); 181 assertEquals(Insets.of(0, 90, 0, 0), mProvider.getInsetsHint()); 182 183 mProvider.setServerVisible(false); 184 statusBar.getFrame().set(0, 0, 500, 80); 185 mProvider.updateSourceFrame(statusBar.getFrame()); 186 assertTrue(mProvider.getSource().getFrame().isEmpty()); 187 assertEquals(Insets.of(0, 90, 0, 0), mProvider.getInsetsHint()); 188 189 // Only change the visibility but not the frame. 190 mProvider.setServerVisible(true); 191 assertEquals(statusBar.getFrame(), mProvider.getSource().getFrame()); 192 assertEquals(Insets.of(0, 80, 0, 0), mProvider.getInsetsHint()); 193 } 194 195 @Test testUpdateSourceFrameForIme()196 public void testUpdateSourceFrameForIme() { 197 final WindowState inputMethod = createWindow(null, TYPE_INPUT_METHOD, "inputMethod"); 198 199 inputMethod.getFrame().set(new Rect(0, 400, 500, 500)); 200 201 mImeProvider.setWindowContainer(inputMethod, null, null); 202 mImeProvider.setServerVisible(false); 203 mImeSource.setVisible(true); 204 mImeProvider.updateSourceFrame(inputMethod.getFrame()); 205 assertEquals(new Rect(0, 0, 0, 0), mImeSource.getFrame()); 206 Insets insets = mImeSource.calculateInsets(new Rect(0, 0, 500, 500), 207 false /* ignoreVisibility */); 208 assertEquals(Insets.of(0, 0, 0, 0), insets); 209 210 mImeProvider.setServerVisible(true); 211 mImeSource.setVisible(true); 212 mImeProvider.updateSourceFrame(inputMethod.getFrame()); 213 assertEquals(inputMethod.getFrame(), mImeSource.getFrame()); 214 insets = mImeSource.calculateInsets(new Rect(0, 0, 500, 500), 215 false /* ignoreVisibility */); 216 assertEquals(Insets.of(0, 0, 0, 100), insets); 217 } 218 219 @Test testSetRequestedVisibleTypes()220 public void testSetRequestedVisibleTypes() { 221 final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); 222 final WindowState target = createWindow(null, TYPE_APPLICATION, "target"); 223 statusBar.getFrame().set(0, 0, 500, 100); 224 mProvider.setWindowContainer(statusBar, null, null); 225 mProvider.updateControlForTarget(target, false /* force */); 226 target.setRequestedVisibleTypes(0, statusBars()); 227 mProvider.updateClientVisibility(target); 228 assertFalse(mSource.isVisible()); 229 } 230 231 @Test testSetRequestedVisibleTypes_noControl()232 public void testSetRequestedVisibleTypes_noControl() { 233 final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); 234 final WindowState target = createWindow(null, TYPE_APPLICATION, "target"); 235 statusBar.getFrame().set(0, 0, 500, 100); 236 mProvider.setWindowContainer(statusBar, null, null); 237 target.setRequestedVisibleTypes(0, statusBars()); 238 mProvider.updateClientVisibility(target); 239 assertTrue(mSource.isVisible()); 240 } 241 242 @Test testInsetGeometries()243 public void testInsetGeometries() { 244 final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); 245 statusBar.getFrame().set(0, 0, 500, 100); 246 statusBar.mHasSurface = true; 247 mProvider.setWindowContainer(statusBar, null, null); 248 mProvider.updateSourceFrame(statusBar.getFrame()); 249 mProvider.onPostLayout(); 250 assertEquals(new Rect(0, 0, 500, 100), mProvider.getSource().getFrame()); 251 // Still apply top insets if window overlaps even if it's top doesn't exactly match 252 // the inset-window's top. 253 assertEquals(Insets.of(0, 100, 0, 0), 254 mProvider.getSource().calculateInsets(new Rect(0, -100, 500, 400), 255 false /* ignoreVisibility */)); 256 257 // Don't apply left insets if window is left-of inset-window but still overlaps 258 statusBar.getFrame().set(100, 0, 0, 0); 259 assertEquals(Insets.of(0, 0, 0, 0), 260 mProvider.getSource().calculateInsets(new Rect(-100, 0, 400, 500), 261 false /* ignoreVisibility */)); 262 } 263 } 264