blob: 53ede60e9ac762d9cdb85545f4edaa2df0c0993e [file] [log] [blame]
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -07001/*
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
chaviw0315a1a2018-03-05 15:28:35 -080017package com.android.server.wm;
18
wilsonshih5ebc8852020-04-09 13:43:52 +080019import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
20import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
21import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Vadim Caenb46f9232020-02-14 17:54:39 +010022import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
Lucas Dupin13f4b8a2020-02-19 13:41:52 -080023import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
24import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
25import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
chaviw0315a1a2018-03-05 15:28:35 -080026import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
27
Lucas Dupin13f4b8a2020-02-19 13:41:52 -080028import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090029import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
Lucas Dupin13f4b8a2020-02-19 13:41:52 -080030import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090031import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
32
Vadim Caenb46f9232020-02-14 17:54:39 +010033import static org.junit.Assert.assertEquals;
Vishnu Naire6e2b0f2019-02-21 10:41:00 -080034import static org.junit.Assert.assertFalse;
35import static org.junit.Assert.assertTrue;
Lucas Dupin13f4b8a2020-02-19 13:41:52 -080036import static org.mockito.ArgumentMatchers.anyBoolean;
37import static org.mockito.ArgumentMatchers.anyFloat;
38import static org.mockito.ArgumentMatchers.eq;
39import static org.mockito.Mockito.verify;
chaviw0315a1a2018-03-05 15:28:35 -080040
Vadim Caenb46f9232020-02-14 17:54:39 +010041import android.content.pm.ActivityInfo;
42import android.content.res.Configuration;
43import android.graphics.Rect;
chaviw0315a1a2018-03-05 15:28:35 -080044import android.os.IBinder;
Lucas Dupin13f4b8a2020-02-19 13:41:52 -080045import android.os.RemoteException;
chaviw0315a1a2018-03-05 15:28:35 -080046import android.platform.test.annotations.Presubmit;
Vadim Caenb46f9232020-02-14 17:54:39 +010047import android.view.DisplayInfo;
48import android.view.Gravity;
49import android.view.Surface;
50import android.view.WindowManager;
Brett Chabota26eda92018-07-23 13:08:30 -070051
52import androidx.test.filters.SmallTest;
chaviw0315a1a2018-03-05 15:28:35 -080053
Vadim Caenb46f9232020-02-14 17:54:39 +010054import com.android.server.wm.utils.WmDisplayCutout;
55
chaviw0315a1a2018-03-05 15:28:35 -080056import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +080057import org.junit.runner.RunWith;
chaviw0315a1a2018-03-05 15:28:35 -080058
59/**
60 * Tests for the {@link WallpaperController} class.
61 *
62 * Build/Install/Run:
Vishnu Naire6e2b0f2019-02-21 10:41:00 -080063 * atest WmTests:WallpaperControllerTests
chaviw0315a1a2018-03-05 15:28:35 -080064 */
65@SmallTest
66@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +080067@RunWith(WindowTestRunner.class)
chaviw0315a1a2018-03-05 15:28:35 -080068public class WallpaperControllerTests extends WindowTestsBase {
69 @Test
70 public void testWallpaperScreenshot() {
71 WindowSurfaceController windowSurfaceController = mock(WindowSurfaceController.class);
72
Riddle Hsu73f53572019-09-23 23:13:01 +080073 // No wallpaper
74 final DisplayContent dc = createNewDisplay();
75 assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
chaviw0315a1a2018-03-05 15:28:35 -080076
Riddle Hsu73f53572019-09-23 23:13:01 +080077 // No wallpaper WSA Surface
78 WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
79 true, dc, true /* ownerCanManageAppTokens */);
80 WindowState wallpaperWindow = createWindow(null /* parent */, TYPE_WALLPAPER,
81 wallpaperWindowToken, "wallpaperWindow");
82 assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
chaviw0315a1a2018-03-05 15:28:35 -080083
Riddle Hsu73f53572019-09-23 23:13:01 +080084 // Wallpaper with not visible WSA surface.
85 wallpaperWindow.mWinAnimator.mSurfaceController = windowSurfaceController;
86 wallpaperWindow.mWinAnimator.mLastAlpha = 1;
87 assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
chaviw0315a1a2018-03-05 15:28:35 -080088
Riddle Hsu73f53572019-09-23 23:13:01 +080089 when(windowSurfaceController.getShown()).thenReturn(true);
chaviw0315a1a2018-03-05 15:28:35 -080090
Riddle Hsu73f53572019-09-23 23:13:01 +080091 // Wallpaper with WSA alpha set to 0.
92 wallpaperWindow.mWinAnimator.mLastAlpha = 0;
93 assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
chaviw0315a1a2018-03-05 15:28:35 -080094
Riddle Hsu73f53572019-09-23 23:13:01 +080095 // Wallpaper window with WSA Surface
96 wallpaperWindow.mWinAnimator.mLastAlpha = 1;
97 assertTrue(dc.mWallpaperController.canScreenshotWallpaper());
chaviw0315a1a2018-03-05 15:28:35 -080098 }
Vadim Caenb46f9232020-02-14 17:54:39 +010099
100 @Test
101 public void testWallpaperSizeWithFixedTransform() {
102 // No wallpaper
103 final DisplayContent dc = createNewDisplay();
Vadim Caenb46f9232020-02-14 17:54:39 +0100104
105 // No wallpaper WSA Surface
106 WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
107 true, dc, true /* ownerCanManageAppTokens */);
108 WindowState wallpaperWindow = createWindow(null /* parent */, TYPE_WALLPAPER,
109 wallpaperWindowToken, "wallpaperWindow");
110
111 WindowManager.LayoutParams attrs = wallpaperWindow.getAttrs();
112 Rect bounds = dc.getBounds();
113 int displayHeight = dc.getBounds().height();
114
115 // Use a wallpaper with a different ratio than the display
116 int wallpaperWidth = bounds.width() * 2;
117 int wallpaperHeight = (int) (bounds.height() * 1.10);
118
119 // Simulate what would be done on the client's side
120 attrs.width = wallpaperWidth;
121 attrs.height = wallpaperHeight;
122 attrs.flags |= FLAG_LAYOUT_NO_LIMITS;
123 attrs.gravity = Gravity.TOP | Gravity.LEFT;
124 wallpaperWindow.getWindowFrames().mParentFrame.set(dc.getBounds());
125
126 // Calling layoutWindowLw a first time, so adjustWindowParams gets the correct data
127 dc.getDisplayPolicy().layoutWindowLw(wallpaperWindow, null, dc.mDisplayFrames);
128
129 wallpaperWindowToken.adjustWindowParams(wallpaperWindow, attrs);
130 dc.getDisplayPolicy().layoutWindowLw(wallpaperWindow, null, dc.mDisplayFrames);
131
132 assertEquals(Configuration.ORIENTATION_PORTRAIT, dc.getConfiguration().orientation);
133 int expectedWidth = (int) (wallpaperWidth * (displayHeight / (double) wallpaperHeight));
134
135 // Check that the wallpaper is correctly scaled
136 assertEquals(new Rect(0, 0, expectedWidth, displayHeight), wallpaperWindow.getFrameLw());
137 Rect portraitFrame = wallpaperWindow.getFrameLw();
138
139 // Rotate the display
140 dc.getDisplayRotation().updateOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, true);
141 dc.sendNewConfiguration();
142
143 // Apply the fixed transform
144 Configuration config = new Configuration();
145 final DisplayInfo info = dc.computeScreenConfiguration(config, Surface.ROTATION_0);
146 final WmDisplayCutout cutout = dc.calculateDisplayCutoutForRotation(Surface.ROTATION_0);
147 final DisplayFrames displayFrames = new DisplayFrames(dc.getDisplayId(), info, cutout);
148 wallpaperWindowToken.applyFixedRotationTransform(info, displayFrames, config);
149
150 // Check that the wallpaper has the same frame in landscape than in portrait
151 assertEquals(Configuration.ORIENTATION_LANDSCAPE, dc.getConfiguration().orientation);
152 assertEquals(portraitFrame, wallpaperWindow.getFrameLw());
153 }
Lucas Dupin13f4b8a2020-02-19 13:41:52 -0800154
155 @Test
156 public void testWallpaperZoom() throws RemoteException {
157 final DisplayContent dc = mWm.mRoot.getDefaultDisplay();
158 final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
159 mock(IBinder.class), true, dc, true /* ownerCanManageAppTokens */);
160 final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken,
161 "wallpaperWindow");
162 wallpaperWindow.getAttrs().privateFlags |=
163 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
164
165 final WindowState homeWindow = createWallpaperTargetWindow(dc);
166
167 spyOn(dc.mWallpaperController);
168 doReturn(true).when(dc.mWallpaperController).isWallpaperVisible();
169
170 dc.mWallpaperController.adjustWallpaperWindows();
171
172 spyOn(wallpaperWindow.mClient);
173
174 float zoom = .5f;
175 dc.mWallpaperController.setWallpaperZoomOut(homeWindow, zoom);
176 assertEquals(zoom, wallpaperWindow.mWallpaperZoomOut, .01f);
177 verify(wallpaperWindow.mClient).dispatchWallpaperOffsets(anyFloat(), anyFloat(), anyFloat(),
178 anyFloat(), eq(zoom), anyBoolean());
179 }
180
181 @Test
182 public void testWallpaperZoom_shouldNotScaleWallpaper() throws RemoteException {
183 final DisplayContent dc = mWm.mRoot.getDefaultDisplay();
184 final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
185 mock(IBinder.class), true, dc, true /* ownerCanManageAppTokens */);
186 final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken,
187 "wallpaperWindow");
188 wallpaperWindow.getAttrs().privateFlags |=
189 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
190
191 final WindowState homeWindow = createWallpaperTargetWindow(dc);
192
193 spyOn(dc.mWallpaperController);
194 doReturn(true).when(dc.mWallpaperController).isWallpaperVisible();
195
196 dc.mWallpaperController.adjustWallpaperWindows();
197
198 spyOn(wallpaperWindow.mClient);
199
200 float newZoom = .5f;
201 wallpaperWindow.mShouldScaleWallpaper = false;
202 // Set zoom, and make sure the window animator scale didn't actually change, but the zoom
203 // value did, and we do dispatch the zoom to the wallpaper service
204 dc.mWallpaperController.setWallpaperZoomOut(homeWindow, newZoom);
205 assertEquals(newZoom, wallpaperWindow.mWallpaperZoomOut, .01f);
206 assertEquals(1f, wallpaperWindow.mWinAnimator.mWallpaperScale, .01f);
207 verify(wallpaperWindow.mClient).dispatchWallpaperOffsets(anyFloat(), anyFloat(), anyFloat(),
208 anyFloat(), eq(newZoom), anyBoolean());
209 }
210
211 @Test
212 public void testWallpaperZoom_multipleCallers() {
213 final DisplayContent dc = mWm.mRoot.getDefaultDisplay();
214 final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
215 mock(IBinder.class), true, dc,
216 true /* ownerCanManageAppTokens */);
217 final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken,
218 "wallpaperWindow");
219 wallpaperWindow.getAttrs().privateFlags |=
220 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
221
222
223 spyOn(dc.mWallpaperController);
224 doReturn(true).when(dc.mWallpaperController).isWallpaperVisible();
225
226 final WindowState homeWindow = createWallpaperTargetWindow(dc);
227
228 WindowState otherWindow = createWindow(null /* parent */, TYPE_APPLICATION, dc,
229 "otherWindow");
230
231 dc.mWallpaperController.adjustWallpaperWindows();
232
233 spyOn(wallpaperWindow.mClient);
234
235 // Set zoom from 2 windows
236 float homeWindowInitialZoom = .5f;
237 float otherWindowInitialZoom = .7f;
238 dc.mWallpaperController.setWallpaperZoomOut(homeWindow, homeWindowInitialZoom);
239 dc.mWallpaperController.setWallpaperZoomOut(otherWindow, otherWindowInitialZoom);
240 // Make sure the largest one wins
241 assertEquals(otherWindowInitialZoom, wallpaperWindow.mWallpaperZoomOut, .01f);
242
243 // Change zoom to a larger zoom from homeWindow
244 float homeWindowZoom2 = .8f;
245 dc.mWallpaperController.setWallpaperZoomOut(homeWindow, homeWindowZoom2);
246 // New zoom should be current
247 assertEquals(homeWindowZoom2, wallpaperWindow.mWallpaperZoomOut, .01f);
248
249 // Set homeWindow zoom to a lower zoom, but keep the one from otherWindow
250 dc.mWallpaperController.setWallpaperZoomOut(homeWindow, homeWindowInitialZoom);
251
252 // Zoom from otherWindow should be the current.
253 assertEquals(otherWindowInitialZoom, wallpaperWindow.mWallpaperZoomOut, .01f);
254 }
255
wilsonshih5ebc8852020-04-09 13:43:52 +0800256 /**
257 * Tests that the windowing mode of the wallpaper window must always be fullscreen.
258 */
259 @Test
260 public void testWallpaperTokenWindowingMode() {
261 final DisplayContent dc = mWm.mRoot.getDefaultDisplay();
262 final WallpaperWindowToken token = new WallpaperWindowToken(mWm, mock(IBinder.class),
263 true, dc, true /* ownerCanManageAppTokens */);
264
265 // The wallpaper should have requested override fullscreen windowing mode, so the
266 // configuration (windowing mode) propagation from display won't change it.
267 dc.setWindowingMode(WINDOWING_MODE_FREEFORM);
268 assertEquals(WINDOWING_MODE_FULLSCREEN, token.getWindowingMode());
269 dc.setWindowingMode(WINDOWING_MODE_UNDEFINED);
270 assertEquals(WINDOWING_MODE_FULLSCREEN, token.getWindowingMode());
271 }
Lucas Dupin13f4b8a2020-02-19 13:41:52 -0800272
Riddle Hsu25fb4912020-05-05 17:20:32 +0800273 @Test
274 public void testFixedRotationRecentsAnimatingTask() {
275 final RecentsAnimationController recentsController = mock(RecentsAnimationController.class);
276 doReturn(true).when(recentsController).isWallpaperVisible(eq(mAppWindow));
277 mWm.setRecentsAnimationController(recentsController);
278
279 mAppWindow.mActivityRecord.applyFixedRotationTransform(mDisplayContent.getDisplayInfo(),
280 mDisplayContent.mDisplayFrames, mDisplayContent.getConfiguration());
281 mAppWindow.mActivityRecord.mVisibleRequested = true;
282 mDisplayContent.mWallpaperController.adjustWallpaperWindows();
283
284 assertEquals(mAppWindow, mDisplayContent.mWallpaperController.getWallpaperTarget());
285 // Wallpaper should link the transform of its target.
286 assertTrue(mAppWindow.mActivityRecord.hasFixedRotationTransform());
287
288 mAppWindow.mActivityRecord.finishFixedRotationTransform();
289 // Invisible requested activity should not share its rotation transform.
290 mAppWindow.mActivityRecord.mVisibleRequested = false;
291 mDisplayContent.mWallpaperController.adjustWallpaperWindows();
292
293 assertFalse(mAppWindow.mActivityRecord.hasFixedRotationTransform());
294 }
295
Lucas Dupin13f4b8a2020-02-19 13:41:52 -0800296 private WindowState createWallpaperTargetWindow(DisplayContent dc) {
297 final ActivityRecord homeActivity = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700298 .setStack(dc.getDefaultTaskDisplayArea().getRootHomeTask())
Lucas Dupin13f4b8a2020-02-19 13:41:52 -0800299 .setCreateTask(true)
300 .build();
301 homeActivity.setVisibility(true);
302
303 WindowState appWindow = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
304 homeActivity, "wallpaperTargetWindow");
305 appWindow.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
306 appWindow.mHasSurface = true;
307 spyOn(appWindow);
308 doReturn(true).when(appWindow).isDrawFinishedLw();
309
310 homeActivity.addWindow(appWindow);
311 return appWindow;
312 }
chaviw0315a1a2018-03-05 15:28:35 -0800313}