blob: 4ab88877fc2b346d6926c831b8c292fd799a3f55 [file] [log] [blame]
Wale Ogunwalee8069dc2015-08-18 09:52:01 -07001/*
2 * Copyright (C) 2015 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
Wale Ogunwale3797c222015-10-27 14:21:58 -070019import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070020import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070021import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070022import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -070023import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080024import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080025import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
26import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
27import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
28import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070029import static com.android.server.wm.WindowManagerService.H.WALLPAPER_DRAW_PENDING_TIMEOUT;
30import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
31import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
32
33import android.os.Bundle;
34import android.os.Debug;
35import android.os.IBinder;
36import android.os.RemoteException;
37import android.os.SystemClock;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -070038import android.util.ArraySet;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070039import android.util.Slog;
40import android.view.DisplayInfo;
41import android.view.WindowManager;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070042
43import java.io.PrintWriter;
44import java.util.ArrayList;
45
46/**
47 * Controls wallpaper windows visibility, ordering, and so on.
48 * NOTE: All methods in this class must be called with the window manager service lock held.
49 */
50class WallpaperController {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080051 private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperController" : TAG_WM;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070052 final private WindowManagerService mService;
53
54 private final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<>();
55
56 // If non-null, this is the currently visible window that is associated
57 // with the wallpaper.
58 private WindowState mWallpaperTarget = null;
59 // If non-null, we are in the middle of animating from one wallpaper target
60 // to another, and this is the lower one in Z-order.
61 private WindowState mLowerWallpaperTarget = null;
62 // If non-null, we are in the middle of animating from one wallpaper target
63 // to another, and this is the higher one in Z-order.
64 private WindowState mUpperWallpaperTarget = null;
65
66 private int mWallpaperAnimLayerAdjustment;
67
68 private float mLastWallpaperX = -1;
69 private float mLastWallpaperY = -1;
70 private float mLastWallpaperXStep = -1;
71 private float mLastWallpaperYStep = -1;
72 private int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE;
73 private int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE;
74
75 // This is set when we are waiting for a wallpaper to tell us it is done
76 // changing its scroll position.
77 WindowState mWaitingOnWallpaper;
78
79 // The last time we had a timeout when waiting for a wallpaper.
80 private long mLastWallpaperTimeoutTime;
81 // We give a wallpaper up to 150ms to finish scrolling.
82 private static final long WALLPAPER_TIMEOUT = 150;
83 // Time we wait after a timeout before trying to wait again.
84 private static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
85
86 // Set to the wallpaper window we would like to hide once the transition animations are done.
87 // This is useful in cases where we don't want the wallpaper to be hidden when the close app
88 // is a wallpaper target and is done animating out, but the opening app isn't a wallpaper
89 // target and isn't done animating in.
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070090 WindowState mDeferredHideWallpaper = null;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070091
92 // We give a wallpaper up to 500ms to finish drawing before playing app transitions.
93 private static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 500;
94 private static final int WALLPAPER_DRAW_NORMAL = 0;
95 private static final int WALLPAPER_DRAW_PENDING = 1;
96 private static final int WALLPAPER_DRAW_TIMEOUT = 2;
97 private int mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
98
Wale Ogunwale5f61d042015-08-20 10:09:47 -070099 private final FindWallpaperTargetResult mFindResults = new FindWallpaperTargetResult();
100
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700101 public WallpaperController(WindowManagerService service) {
102 mService = service;
103 }
104
105 WindowState getWallpaperTarget() {
106 return mWallpaperTarget;
107 }
108
109 WindowState getLowerWallpaperTarget() {
110 return mLowerWallpaperTarget;
111 }
112
113 WindowState getUpperWallpaperTarget() {
114 return mUpperWallpaperTarget;
115 }
116
117 boolean isWallpaperTarget(WindowState win) {
118 return win == mWallpaperTarget;
119 }
120
121 boolean isBelowWallpaperTarget(WindowState win) {
122 return mWallpaperTarget != null && mWallpaperTarget.mLayer >= win.mBaseLayer;
123 }
124
125 boolean isWallpaperVisible() {
126 return isWallpaperVisible(mWallpaperTarget);
127 }
128
129 private boolean isWallpaperVisible(WindowState wallpaperTarget) {
130 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
131 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
132 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
133 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
134 + " upper=" + mUpperWallpaperTarget
135 + " lower=" + mLowerWallpaperTarget);
136 return (wallpaperTarget != null
137 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
138 && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
139 || mUpperWallpaperTarget != null
140 || mLowerWallpaperTarget != null;
141 }
142
143 boolean isWallpaperTargetAnimating() {
Jorim Jaggi5c80c412016-04-19 20:03:47 -0700144 return mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimationSet()
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700145 && !mWallpaperTarget.mWinAnimator.isDummyAnimation();
146 }
147
148 void updateWallpaperVisibility() {
Filip Gruszczynski63a35e22015-11-05 15:38:59 -0800149 final boolean visible = isWallpaperVisible(mWallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700150
151 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700152 final WindowToken token = mWallpaperTokens.get(curTokenNdx);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700153 token.updateWallpaperVisibility(visible);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700154 }
155 }
156
157 void hideDeferredWallpapersIfNeeded() {
158 if (mDeferredHideWallpaper != null) {
159 hideWallpapers(mDeferredHideWallpaper);
160 mDeferredHideWallpaper = null;
161 }
162 }
163
164 void hideWallpapers(final WindowState winGoingAway) {
165 if (mWallpaperTarget != null
166 && (mWallpaperTarget != winGoingAway || mLowerWallpaperTarget != null)) {
167 return;
168 }
169 if (mService.mAppTransition.isRunning()) {
170 // Defer hiding the wallpaper when app transition is running until the animations
171 // are done.
172 mDeferredHideWallpaper = winGoingAway;
173 return;
174 }
175
176 final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway);
177 for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
178 final WindowToken token = mWallpaperTokens.get(i);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700179 token.hideWallpaperToken(wasDeferred, "hideWallpapers");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700180 if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
181 + " from " + winGoingAway + " target=" + mWallpaperTarget + " lower="
182 + mLowerWallpaperTarget + "\n" + Debug.getCallers(5, " "));
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700183 }
184 }
185
186 boolean updateWallpaperOffset(WindowState wallpaperWin, int dw, int dh, boolean sync) {
187 boolean rawChanged = false;
Winson4b4ba902016-07-27 19:45:52 -0700188 // Set the default wallpaper x-offset to either edge of the screen (depending on RTL), to
189 // match the behavior of most Launchers
190 float defaultWallpaperX = wallpaperWin.isRtl() ? 1f : 0f;
191 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : defaultWallpaperX;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700192 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
193 int availw = wallpaperWin.mFrame.right - wallpaperWin.mFrame.left - dw;
194 int offset = availw > 0 ? -(int)(availw * wpx + .5f) : 0;
195 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
196 offset += mLastWallpaperDisplayOffsetX;
197 }
198 boolean changed = wallpaperWin.mXOffset != offset;
199 if (changed) {
200 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " x: " + offset);
201 wallpaperWin.mXOffset = offset;
202 }
203 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
204 wallpaperWin.mWallpaperX = wpx;
205 wallpaperWin.mWallpaperXStep = wpxs;
206 rawChanged = true;
207 }
208
209 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
210 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
211 int availh = wallpaperWin.mFrame.bottom - wallpaperWin.mFrame.top - dh;
212 offset = availh > 0 ? -(int)(availh * wpy + .5f) : 0;
213 if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
214 offset += mLastWallpaperDisplayOffsetY;
215 }
216 if (wallpaperWin.mYOffset != offset) {
217 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " y: " + offset);
218 changed = true;
219 wallpaperWin.mYOffset = offset;
220 }
221 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
222 wallpaperWin.mWallpaperY = wpy;
223 wallpaperWin.mWallpaperYStep = wpys;
224 rawChanged = true;
225 }
226
227 if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
228 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
229 try {
230 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
231 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
232 + " y=" + wallpaperWin.mWallpaperY);
233 if (sync) {
234 mWaitingOnWallpaper = wallpaperWin;
235 }
236 wallpaperWin.mClient.dispatchWallpaperOffsets(
237 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
238 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
239 if (sync) {
240 if (mWaitingOnWallpaper != null) {
241 long start = SystemClock.uptimeMillis();
242 if ((mLastWallpaperTimeoutTime + WALLPAPER_TIMEOUT_RECOVERY)
243 < start) {
244 try {
245 if (DEBUG_WALLPAPER) Slog.v(TAG,
246 "Waiting for offset complete...");
247 mService.mWindowMap.wait(WALLPAPER_TIMEOUT);
248 } catch (InterruptedException e) {
249 }
250 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
251 if ((start + WALLPAPER_TIMEOUT) < SystemClock.uptimeMillis()) {
252 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
253 + wallpaperWin);
254 mLastWallpaperTimeoutTime = start;
255 }
256 }
257 mWaitingOnWallpaper = null;
258 }
259 }
260 } catch (RemoteException e) {
261 }
262 }
263
264 return changed;
265 }
266
267 void setWindowWallpaperPosition(
268 WindowState window, float x, float y, float xStep, float yStep) {
269 if (window.mWallpaperX != x || window.mWallpaperY != y) {
270 window.mWallpaperX = x;
271 window.mWallpaperY = y;
272 window.mWallpaperXStep = xStep;
273 window.mWallpaperYStep = yStep;
274 updateWallpaperOffsetLocked(window, true);
275 }
276 }
277
278 void setWindowWallpaperDisplayOffset(WindowState window, int x, int y) {
279 if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y) {
280 window.mWallpaperDisplayOffsetX = x;
281 window.mWallpaperDisplayOffsetY = y;
282 updateWallpaperOffsetLocked(window, true);
283 }
284 }
285
286 Bundle sendWindowWallpaperCommand(
287 WindowState window, String action, int x, int y, int z, Bundle extras, boolean sync) {
288 if (window == mWallpaperTarget
289 || window == mLowerWallpaperTarget
290 || window == mUpperWallpaperTarget) {
291 boolean doWait = sync;
292 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700293 final WindowToken token = mWallpaperTokens.get(curTokenNdx);
294 token.sendWindowWallpaperCommand(action, x, y, z, extras, sync);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700295 }
296
297 if (doWait) {
298 // TODO: Need to wait for result.
299 }
300 }
301
302 return null;
303 }
304
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700305 private void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700306 final DisplayContent displayContent = changingTarget.getDisplayContent();
307 if (displayContent == null) {
308 return;
309 }
310 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
311 final int dw = displayInfo.logicalWidth;
312 final int dh = displayInfo.logicalHeight;
313
314 WindowState target = mWallpaperTarget;
315 if (target != null) {
316 if (target.mWallpaperX >= 0) {
317 mLastWallpaperX = target.mWallpaperX;
318 } else if (changingTarget.mWallpaperX >= 0) {
319 mLastWallpaperX = changingTarget.mWallpaperX;
320 }
321 if (target.mWallpaperY >= 0) {
322 mLastWallpaperY = target.mWallpaperY;
323 } else if (changingTarget.mWallpaperY >= 0) {
324 mLastWallpaperY = changingTarget.mWallpaperY;
325 }
326 if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
327 mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
328 } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
329 mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
330 }
331 if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
332 mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
333 } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
334 mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
335 }
336 if (target.mWallpaperXStep >= 0) {
337 mLastWallpaperXStep = target.mWallpaperXStep;
338 } else if (changingTarget.mWallpaperXStep >= 0) {
339 mLastWallpaperXStep = changingTarget.mWallpaperXStep;
340 }
341 if (target.mWallpaperYStep >= 0) {
342 mLastWallpaperYStep = target.mWallpaperYStep;
343 } else if (changingTarget.mWallpaperYStep >= 0) {
344 mLastWallpaperYStep = changingTarget.mWallpaperYStep;
345 }
346 }
347
348 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700349 mWallpaperTokens.get(curTokenNdx).updateWallpaperOffset(dw, dh, sync);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700350 }
351 }
352
353 void clearLastWallpaperTimeoutTime() {
354 mLastWallpaperTimeoutTime = 0;
355 }
356
357 void wallpaperCommandComplete(IBinder window) {
358 if (mWaitingOnWallpaper != null &&
359 mWaitingOnWallpaper.mClient.asBinder() == window) {
360 mWaitingOnWallpaper = null;
361 mService.mWindowMap.notifyAll();
362 }
363 }
364
365 void wallpaperOffsetsComplete(IBinder window) {
366 if (mWaitingOnWallpaper != null &&
367 mWaitingOnWallpaper.mClient.asBinder() == window) {
368 mWaitingOnWallpaper = null;
369 mService.mWindowMap.notifyAll();
370 }
371 }
372
373 int getAnimLayerAdjustment() {
374 return mWallpaperAnimLayerAdjustment;
375 }
376
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700377 private void findWallpaperTarget(WindowList windows, FindWallpaperTargetResult result) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700378 final WindowAnimator winAnimator = mService.mAnimator;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700379 result.reset();
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700380 WindowState w = null;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700381 int windowDetachedI = -1;
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700382 boolean resetTopWallpaper = false;
383 boolean inFreeformSpace = false;
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800384 boolean replacing = false;
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700385 boolean keyguardGoingAwayWithWallpaper = false;
386
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700387 for (int i = windows.size() - 1; i >= 0; i--) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700388 w = windows.get(i);
389 if ((w.mAttrs.type == TYPE_WALLPAPER)) {
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700390 if (result.topWallpaper == null || resetTopWallpaper) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700391 result.setTopWallpaper(w, i);
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700392 resetTopWallpaper = false;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700393 }
394 continue;
395 }
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700396 resetTopWallpaper = true;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700397 if (w != winAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
398 // If this window's app token is hidden and not animating,
399 // it is of no interest to us.
400 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
401 if (DEBUG_WALLPAPER) Slog.v(TAG,
402 "Skipping hidden and not animating token: " + w);
403 continue;
404 }
405 }
406 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
407 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
408
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700409 if (!inFreeformSpace) {
410 TaskStack stack = w.getStack();
411 inFreeformSpace = stack != null && stack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
412 }
413
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700414 replacing |= w.mWillReplaceWindow;
415 keyguardGoingAwayWithWallpaper |= (w.mAppToken != null
416 && w.mWinAnimator.mKeyguardGoingAwayWithWallpaper);
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800417
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700418 final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800419 if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700420 if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: #" + i + "=" + w);
421 result.setWallpaperTarget(w, i);
Jorim Jaggi5c80c412016-04-19 20:03:47 -0700422 if (w == mWallpaperTarget && w.mWinAnimator.isAnimationSet()) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700423 // The current wallpaper target is animating, so we'll look behind it for
424 // another possible target and figure out what is going on later.
425 if (DEBUG_WALLPAPER) Slog.v(TAG,
426 "Win " + w + ": token animating, looking behind.");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700427 continue;
428 }
429 break;
430 } else if (w == winAnimator.mWindowDetachedWallpaper) {
431 windowDetachedI = i;
432 }
433 }
434
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700435 if (result.wallpaperTarget != null) {
436 return;
437 }
438
439 if (windowDetachedI >= 0) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700440 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700441 "Found animating detached wallpaper activity: #" + windowDetachedI + "=" + w);
442 result.setWallpaperTarget(w, windowDetachedI);
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700443 } else if (inFreeformSpace || (replacing && mWallpaperTarget != null)) {
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700444 // In freeform mode we set the wallpaper as its own target, so we don't need an
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800445 // additional window to make it visible. When we are replacing a window and there was
446 // wallpaper before replacement, we want to keep the window until the new windows fully
447 // appear and can determine the visibility, to avoid flickering.
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700448 result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700449
450 } else if (keyguardGoingAwayWithWallpaper) {
451 // If the app is executing an animation because the keyguard is going away (and the
452 // keyguard was showing the wallpaper) keep the wallpaper during the animation so it
453 // doesn't flicker out by having it be its own target.
454 result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700455 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700456 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700457
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700458 /** Updates the target wallpaper if needed and returns true if an update happened. */
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700459 private boolean updateWallpaperWindowsTarget(
460 WindowList windows, FindWallpaperTargetResult result) {
461
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700462 WindowState wallpaperTarget = result.wallpaperTarget;
463 int wallpaperTargetIndex = result.wallpaperTargetIndex;
464
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700465 if (mWallpaperTarget == wallpaperTarget
466 || (mLowerWallpaperTarget != null && mLowerWallpaperTarget == wallpaperTarget)) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700467
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700468 if (mLowerWallpaperTarget != null) {
469 // Is it time to stop animating?
470 if (!mLowerWallpaperTarget.isAnimatingLw()
471 || !mUpperWallpaperTarget.isAnimatingLw()) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700472 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700473 "No longer animating wallpaper targets!");
474 mLowerWallpaperTarget = null;
475 mUpperWallpaperTarget = null;
476 mWallpaperTarget = wallpaperTarget;
477 return true;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700478 }
479 }
480
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700481 return false;
482 }
483
484 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
485 "New wallpaper target: " + wallpaperTarget + " oldTarget: " + mWallpaperTarget);
486
487 mLowerWallpaperTarget = null;
488 mUpperWallpaperTarget = null;
489
490 WindowState oldW = mWallpaperTarget;
491 mWallpaperTarget = wallpaperTarget;
492
493 if (wallpaperTarget == null || oldW == null) {
494 return true;
495 }
496
497 // Now what is happening... if the current and new targets are animating,
498 // then we are in our super special mode!
499 boolean oldAnim = oldW.isAnimatingLw();
500 boolean foundAnim = wallpaperTarget.isAnimatingLw();
501 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
502 "New animation: " + foundAnim + " old animation: " + oldAnim);
503
504 if (!foundAnim || !oldAnim) {
505 return true;
506 }
507
508 int oldI = windows.indexOf(oldW);
509 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
510 "New i: " + wallpaperTargetIndex + " old i: " + oldI);
511
512 if (oldI < 0) {
513 return true;
514 }
515
516 final boolean newTargetHidden = wallpaperTarget.mAppToken != null
517 && wallpaperTarget.mAppToken.hiddenRequested;
518 final boolean oldTargetHidden = oldW.mAppToken != null
519 && oldW.mAppToken.hiddenRequested;
520
521 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Animating wallpapers:" + " old#" + oldI + "="
522 + oldW + " hidden=" + oldTargetHidden + " new#" + wallpaperTargetIndex + "="
523 + wallpaperTarget + " hidden=" + newTargetHidden);
524
525 // Set the upper and lower wallpaper targets correctly,
526 // and make sure that we are positioning the wallpaper below the lower.
527 if (wallpaperTargetIndex > oldI) {
528 // The new target is on top of the old one.
529 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Found target above old target.");
530 mUpperWallpaperTarget = wallpaperTarget;
531 mLowerWallpaperTarget = oldW;
532
533 wallpaperTarget = oldW;
534 wallpaperTargetIndex = oldI;
535 } else {
536 // The new target is below the old one.
537 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Found target below old target.");
538 mUpperWallpaperTarget = oldW;
539 mLowerWallpaperTarget = wallpaperTarget;
540 }
541
542 if (newTargetHidden && !oldTargetHidden) {
543 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Old wallpaper still the target.");
544 // Use the old target if new target is hidden but old target
545 // is not. If they're both hidden, still use the new target.
546 mWallpaperTarget = oldW;
547 } else if (newTargetHidden == oldTargetHidden
548 && !mService.mOpeningApps.contains(wallpaperTarget.mAppToken)
549 && (mService.mOpeningApps.contains(oldW.mAppToken)
550 || mService.mClosingApps.contains(oldW.mAppToken))) {
551 // If they're both hidden (or both not hidden), prefer the one that's currently in
552 // opening or closing app list, this allows transition selection logic to better
553 // determine the wallpaper status of opening/closing apps.
554 mWallpaperTarget = oldW;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700555 }
556
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700557 result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700558 return true;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700559 }
560
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700561 private boolean updateWallpaperWindowsTargetByLayer(WindowList windows,
562 FindWallpaperTargetResult result) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700563
564 WindowState wallpaperTarget = result.wallpaperTarget;
565 int wallpaperTargetIndex = result.wallpaperTargetIndex;
566 boolean visible = wallpaperTarget != null;
567
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700568 if (visible) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700569 // The window is visible to the compositor...but is it visible to the user?
570 // That is what the wallpaper cares about.
571 visible = isWallpaperVisible(wallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700572 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
573
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700574 // If the wallpaper target is animating, we may need to copy its layer adjustment.
575 // Only do this if we are not transferring between two wallpaper targets.
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700576 mWallpaperAnimLayerAdjustment =
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700577 (mLowerWallpaperTarget == null && wallpaperTarget.mAppToken != null)
578 ? wallpaperTarget.mAppToken.mAppAnimator.animLayerAdjustment : 0;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700579
580 final int maxLayer = (mService.mPolicy.getMaxWallpaperLayer() * TYPE_LAYER_MULTIPLIER)
581 + TYPE_LAYER_OFFSET;
582
583 // Now w is the window we are supposed to be behind... but we
584 // need to be sure to also be behind any of its attached windows,
585 // AND any starting window associated with it, AND below the
586 // maximum layer the policy allows for wallpapers.
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700587 while (wallpaperTargetIndex > 0) {
Wale Ogunwalecaa53af2016-07-17 14:50:26 -0700588 final WindowState wb = windows.get(wallpaperTargetIndex - 1);
589 final WindowState wbParentWindow = wb.getParentWindow();
590 final WindowState wallpaperParentWindow = wallpaperTarget.getParentWindow();
591 if (wb.mBaseLayer < maxLayer
592 && wbParentWindow != wallpaperTarget
593 && (wallpaperParentWindow == null || wbParentWindow != wallpaperParentWindow)
594 && (wb.mAttrs.type != TYPE_APPLICATION_STARTING
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700595 || wallpaperTarget.mToken == null
596 || wb.mToken != wallpaperTarget.mToken)) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700597 // This window is not related to the previous one in any
598 // interesting way, so stop here.
599 break;
600 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700601 wallpaperTarget = wb;
602 wallpaperTargetIndex--;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700603 }
604 } else {
605 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
606 }
607
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700608 result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
609 return visible;
610 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700611
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700612 private boolean updateWallpaperWindowsPlacement(WindowList windows,
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700613 WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible) {
614
615 // TODO(multidisplay): Wallpapers on main screen only.
616 final DisplayInfo displayInfo = mService.getDefaultDisplayContentLocked().getDisplayInfo();
617 final int dw = displayInfo.logicalWidth;
618 final int dh = displayInfo.logicalHeight;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700619
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700620 // Start stepping backwards from here, ensuring that our wallpaper windows are correctly placed.
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700621 boolean changed = false;
622 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700623 final WindowToken token = mWallpaperTokens.get(curTokenNdx);
624 changed |= token.updateWallpaperWindowsPlacement(windows, wallpaperTarget,
625 wallpaperTargetIndex, visible, dw, dh, mWallpaperAnimLayerAdjustment);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700626 }
627
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700628 return changed;
629 }
630
Wale Ogunwale0303c572016-10-20 10:16:29 -0700631 boolean adjustWallpaperWindows(WindowList windows) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700632 mService.mRoot.mWallpaperMayChange = false;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700633
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700634 // First find top-most window that has asked to be on top of the wallpaper;
635 // all wallpapers go behind it.
636 findWallpaperTarget(windows, mFindResults);
637 final boolean targetChanged = updateWallpaperWindowsTarget(windows, mFindResults);
638 final boolean visible = updateWallpaperWindowsTargetByLayer(windows, mFindResults);
639 WindowState wallpaperTarget = mFindResults.wallpaperTarget;
640 int wallpaperTargetIndex = mFindResults.wallpaperTargetIndex;
641
642 if (wallpaperTarget == null && mFindResults.topWallpaper != null) {
643 // There is no wallpaper target, so it goes at the bottom.
644 // We will assume it is the same place as last time, if known.
645 wallpaperTarget = mFindResults.topWallpaper;
646 wallpaperTargetIndex = mFindResults.topWallpaperIndex + 1;
647 } else {
648 // Okay i is the position immediately above the wallpaper.
649 // Look at what is below it for later.
650 wallpaperTarget = wallpaperTargetIndex > 0
651 ? windows.get(wallpaperTargetIndex - 1) : null;
652 }
653
654 if (visible) {
655 if (mWallpaperTarget.mWallpaperX >= 0) {
656 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
657 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
658 }
659 if (mWallpaperTarget.mWallpaperY >= 0) {
660 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
661 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
662 }
663 if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
664 mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
665 }
666 if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
667 mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
668 }
669 }
670
671 final boolean changed = updateWallpaperWindowsPlacement(
672 windows, wallpaperTarget, wallpaperTargetIndex, visible);
673
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700674 if (targetChanged && DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, "New wallpaper: target="
675 + mWallpaperTarget + " lower=" + mLowerWallpaperTarget + " upper="
676 + mUpperWallpaperTarget);
677
678 return changed;
679 }
680
681 boolean processWallpaperDrawPendingTimeout() {
682 if (mWallpaperDrawState == WALLPAPER_DRAW_PENDING) {
683 mWallpaperDrawState = WALLPAPER_DRAW_TIMEOUT;
684 if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
685 "*** WALLPAPER DRAW TIMEOUT");
686 return true;
687 }
688 return false;
689 }
690
691 boolean wallpaperTransitionReady() {
692 boolean transitionReady = true;
693 boolean wallpaperReady = true;
694 for (int curTokenIndex = mWallpaperTokens.size() - 1;
695 curTokenIndex >= 0 && wallpaperReady; curTokenIndex--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700696 final WindowToken token = mWallpaperTokens.get(curTokenIndex);
697 if (token.hasVisibleNotDrawnWallpaper()) {
698 // We've told this wallpaper to be visible, but it is not drawn yet
699 wallpaperReady = false;
700 if (mWallpaperDrawState != WALLPAPER_DRAW_TIMEOUT) {
701 // wait for this wallpaper until it is drawn or timeout
702 transitionReady = false;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700703 }
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700704 if (mWallpaperDrawState == WALLPAPER_DRAW_NORMAL) {
705 mWallpaperDrawState = WALLPAPER_DRAW_PENDING;
706 mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
707 mService.mH.sendEmptyMessageDelayed(WALLPAPER_DRAW_PENDING_TIMEOUT,
708 WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION);
709 }
710 if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
711 "Wallpaper should be visible but has not been drawn yet. " +
712 "mWallpaperDrawState=" + mWallpaperDrawState);
713 break;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700714 }
715 }
716 if (wallpaperReady) {
717 mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
718 mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
719 }
720
721 return transitionReady;
722 }
723
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700724 /**
725 * Adjusts the wallpaper windows if the input display has a pending wallpaper layout or one of
726 * the opening apps should be a wallpaper target.
727 */
Wale Ogunwale0303c572016-10-20 10:16:29 -0700728 void adjustWallpaperWindowsForAppTransitionIfNeeded(DisplayContent dc,
729 ArraySet<AppWindowToken> openingApps) {
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700730 boolean adjust = false;
731 if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
732 adjust = true;
733 } else {
734 for (int i = openingApps.size() - 1; i >= 0; --i) {
735 final AppWindowToken token = openingApps.valueAt(i);
736 if (token.windowsCanBeWallpaperTarget()) {
737 adjust = true;
738 break;
739 }
740 }
741 }
742
Wale Ogunwale0303c572016-10-20 10:16:29 -0700743 if (adjust) {
744 dc.adjustWallpaperWindows();
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700745 }
746 }
747
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700748 void addWallpaperToken(WindowToken token) {
749 mWallpaperTokens.add(token);
750 }
751
752 void removeWallpaperToken(WindowToken token) {
753 mWallpaperTokens.remove(token);
754 }
755
756 void dump(PrintWriter pw, String prefix) {
757 pw.print(prefix); pw.print("mWallpaperTarget="); pw.println(mWallpaperTarget);
758 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
759 pw.print(prefix); pw.print("mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
760 pw.print(prefix); pw.print("mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
761 }
762 pw.print(prefix); pw.print("mLastWallpaperX="); pw.print(mLastWallpaperX);
763 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
764 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE
765 || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
766 pw.print(prefix);
767 pw.print("mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX);
768 pw.print(" mLastWallpaperDisplayOffsetY="); pw.println(mLastWallpaperDisplayOffsetY);
769 }
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700770
771 if (mWallpaperAnimLayerAdjustment != 0) {
772 pw.println(prefix + "mWallpaperAnimLayerAdjustment=" + mWallpaperAnimLayerAdjustment);
773 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700774 }
775
776 void dumpTokens(PrintWriter pw, String prefix, boolean dumpAll) {
777 if (!mWallpaperTokens.isEmpty()) {
778 pw.println();
779 pw.print(prefix); pw.println("Wallpaper tokens:");
780 for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
781 WindowToken token = mWallpaperTokens.get(i);
782 pw.print(prefix); pw.print("Wallpaper #"); pw.print(i);
783 pw.print(' '); pw.print(token);
784 if (dumpAll) {
785 pw.println(':');
786 token.dump(pw, " ");
787 } else {
788 pw.println();
789 }
790 }
791 }
792 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700793
794 /** Helper class for storing the results of a wallpaper target find operation. */
795 final private static class FindWallpaperTargetResult {
796 int topWallpaperIndex = 0;
797 WindowState topWallpaper = null;
798 int wallpaperTargetIndex = 0;
799 WindowState wallpaperTarget = null;
800
801 void setTopWallpaper(WindowState win, int index) {
802 topWallpaper = win;
803 topWallpaperIndex = index;
804 }
805
806 void setWallpaperTarget(WindowState win, int index) {
807 wallpaperTarget = win;
808 wallpaperTargetIndex = index;
809 }
810
811 void reset() {
812 topWallpaperIndex = 0;
813 topWallpaper = null;
814 wallpaperTargetIndex = 0;
815 wallpaperTarget = null;
816 }
817 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700818}