blob: 962325f3fcfbaa19c4eb22f21a18a5b73cc97cc0 [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() {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700149 final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
150 if (displayContent == null) {
151 return;
152 }
Filip Gruszczynski63a35e22015-11-05 15:38:59 -0800153 final boolean visible = isWallpaperVisible(mWallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700154 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
155 final int dw = displayInfo.logicalWidth;
156 final int dh = displayInfo.logicalHeight;
157
158 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700159 final WindowToken token = mWallpaperTokens.get(curTokenNdx);
160 token.updateWallpaperVisibility(dw, dh, visible, displayContent);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700161 }
162 }
163
164 void hideDeferredWallpapersIfNeeded() {
165 if (mDeferredHideWallpaper != null) {
166 hideWallpapers(mDeferredHideWallpaper);
167 mDeferredHideWallpaper = null;
168 }
169 }
170
171 void hideWallpapers(final WindowState winGoingAway) {
172 if (mWallpaperTarget != null
173 && (mWallpaperTarget != winGoingAway || mLowerWallpaperTarget != null)) {
174 return;
175 }
176 if (mService.mAppTransition.isRunning()) {
177 // Defer hiding the wallpaper when app transition is running until the animations
178 // are done.
179 mDeferredHideWallpaper = winGoingAway;
180 return;
181 }
182
183 final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway);
184 for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
185 final WindowToken token = mWallpaperTokens.get(i);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700186 token.hideWallpaperToken(wasDeferred, "hideWallpapers");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700187 if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
188 + " from " + winGoingAway + " target=" + mWallpaperTarget + " lower="
189 + mLowerWallpaperTarget + "\n" + Debug.getCallers(5, " "));
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700190 }
191 }
192
193 boolean updateWallpaperOffset(WindowState wallpaperWin, int dw, int dh, boolean sync) {
194 boolean rawChanged = false;
Winson4b4ba902016-07-27 19:45:52 -0700195 // Set the default wallpaper x-offset to either edge of the screen (depending on RTL), to
196 // match the behavior of most Launchers
197 float defaultWallpaperX = wallpaperWin.isRtl() ? 1f : 0f;
198 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : defaultWallpaperX;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700199 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
200 int availw = wallpaperWin.mFrame.right - wallpaperWin.mFrame.left - dw;
201 int offset = availw > 0 ? -(int)(availw * wpx + .5f) : 0;
202 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
203 offset += mLastWallpaperDisplayOffsetX;
204 }
205 boolean changed = wallpaperWin.mXOffset != offset;
206 if (changed) {
207 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " x: " + offset);
208 wallpaperWin.mXOffset = offset;
209 }
210 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
211 wallpaperWin.mWallpaperX = wpx;
212 wallpaperWin.mWallpaperXStep = wpxs;
213 rawChanged = true;
214 }
215
216 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
217 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
218 int availh = wallpaperWin.mFrame.bottom - wallpaperWin.mFrame.top - dh;
219 offset = availh > 0 ? -(int)(availh * wpy + .5f) : 0;
220 if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
221 offset += mLastWallpaperDisplayOffsetY;
222 }
223 if (wallpaperWin.mYOffset != offset) {
224 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " y: " + offset);
225 changed = true;
226 wallpaperWin.mYOffset = offset;
227 }
228 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
229 wallpaperWin.mWallpaperY = wpy;
230 wallpaperWin.mWallpaperYStep = wpys;
231 rawChanged = true;
232 }
233
234 if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
235 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
236 try {
237 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
238 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
239 + " y=" + wallpaperWin.mWallpaperY);
240 if (sync) {
241 mWaitingOnWallpaper = wallpaperWin;
242 }
243 wallpaperWin.mClient.dispatchWallpaperOffsets(
244 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
245 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
246 if (sync) {
247 if (mWaitingOnWallpaper != null) {
248 long start = SystemClock.uptimeMillis();
249 if ((mLastWallpaperTimeoutTime + WALLPAPER_TIMEOUT_RECOVERY)
250 < start) {
251 try {
252 if (DEBUG_WALLPAPER) Slog.v(TAG,
253 "Waiting for offset complete...");
254 mService.mWindowMap.wait(WALLPAPER_TIMEOUT);
255 } catch (InterruptedException e) {
256 }
257 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
258 if ((start + WALLPAPER_TIMEOUT) < SystemClock.uptimeMillis()) {
259 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
260 + wallpaperWin);
261 mLastWallpaperTimeoutTime = start;
262 }
263 }
264 mWaitingOnWallpaper = null;
265 }
266 }
267 } catch (RemoteException e) {
268 }
269 }
270
271 return changed;
272 }
273
274 void setWindowWallpaperPosition(
275 WindowState window, float x, float y, float xStep, float yStep) {
276 if (window.mWallpaperX != x || window.mWallpaperY != y) {
277 window.mWallpaperX = x;
278 window.mWallpaperY = y;
279 window.mWallpaperXStep = xStep;
280 window.mWallpaperYStep = yStep;
281 updateWallpaperOffsetLocked(window, true);
282 }
283 }
284
285 void setWindowWallpaperDisplayOffset(WindowState window, int x, int y) {
286 if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y) {
287 window.mWallpaperDisplayOffsetX = x;
288 window.mWallpaperDisplayOffsetY = y;
289 updateWallpaperOffsetLocked(window, true);
290 }
291 }
292
293 Bundle sendWindowWallpaperCommand(
294 WindowState window, String action, int x, int y, int z, Bundle extras, boolean sync) {
295 if (window == mWallpaperTarget
296 || window == mLowerWallpaperTarget
297 || window == mUpperWallpaperTarget) {
298 boolean doWait = sync;
299 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700300 final WindowToken token = mWallpaperTokens.get(curTokenNdx);
301 token.sendWindowWallpaperCommand(action, x, y, z, extras, sync);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700302 }
303
304 if (doWait) {
305 // TODO: Need to wait for result.
306 }
307 }
308
309 return null;
310 }
311
312 void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
313 final DisplayContent displayContent = changingTarget.getDisplayContent();
314 if (displayContent == null) {
315 return;
316 }
317 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
318 final int dw = displayInfo.logicalWidth;
319 final int dh = displayInfo.logicalHeight;
320
321 WindowState target = mWallpaperTarget;
322 if (target != null) {
323 if (target.mWallpaperX >= 0) {
324 mLastWallpaperX = target.mWallpaperX;
325 } else if (changingTarget.mWallpaperX >= 0) {
326 mLastWallpaperX = changingTarget.mWallpaperX;
327 }
328 if (target.mWallpaperY >= 0) {
329 mLastWallpaperY = target.mWallpaperY;
330 } else if (changingTarget.mWallpaperY >= 0) {
331 mLastWallpaperY = changingTarget.mWallpaperY;
332 }
333 if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
334 mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
335 } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
336 mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
337 }
338 if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
339 mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
340 } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
341 mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
342 }
343 if (target.mWallpaperXStep >= 0) {
344 mLastWallpaperXStep = target.mWallpaperXStep;
345 } else if (changingTarget.mWallpaperXStep >= 0) {
346 mLastWallpaperXStep = changingTarget.mWallpaperXStep;
347 }
348 if (target.mWallpaperYStep >= 0) {
349 mLastWallpaperYStep = target.mWallpaperYStep;
350 } else if (changingTarget.mWallpaperYStep >= 0) {
351 mLastWallpaperYStep = changingTarget.mWallpaperYStep;
352 }
353 }
354
355 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700356 mWallpaperTokens.get(curTokenNdx).updateWallpaperOffset(dw, dh, sync);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700357 }
358 }
359
360 void clearLastWallpaperTimeoutTime() {
361 mLastWallpaperTimeoutTime = 0;
362 }
363
364 void wallpaperCommandComplete(IBinder window) {
365 if (mWaitingOnWallpaper != null &&
366 mWaitingOnWallpaper.mClient.asBinder() == window) {
367 mWaitingOnWallpaper = null;
368 mService.mWindowMap.notifyAll();
369 }
370 }
371
372 void wallpaperOffsetsComplete(IBinder window) {
373 if (mWaitingOnWallpaper != null &&
374 mWaitingOnWallpaper.mClient.asBinder() == window) {
375 mWaitingOnWallpaper = null;
376 mService.mWindowMap.notifyAll();
377 }
378 }
379
380 int getAnimLayerAdjustment() {
381 return mWallpaperAnimLayerAdjustment;
382 }
383
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700384 private void findWallpaperTarget(WindowList windows, FindWallpaperTargetResult result) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700385 final WindowAnimator winAnimator = mService.mAnimator;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700386 result.reset();
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700387 WindowState w = null;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700388 int windowDetachedI = -1;
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700389 boolean resetTopWallpaper = false;
390 boolean inFreeformSpace = false;
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800391 boolean replacing = false;
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700392 boolean keyguardGoingAwayWithWallpaper = false;
393
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700394 for (int i = windows.size() - 1; i >= 0; i--) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700395 w = windows.get(i);
396 if ((w.mAttrs.type == TYPE_WALLPAPER)) {
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700397 if (result.topWallpaper == null || resetTopWallpaper) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700398 result.setTopWallpaper(w, i);
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700399 resetTopWallpaper = false;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700400 }
401 continue;
402 }
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700403 resetTopWallpaper = true;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700404 if (w != winAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
405 // If this window's app token is hidden and not animating,
406 // it is of no interest to us.
407 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
408 if (DEBUG_WALLPAPER) Slog.v(TAG,
409 "Skipping hidden and not animating token: " + w);
410 continue;
411 }
412 }
413 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
414 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
415
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700416 if (!inFreeformSpace) {
417 TaskStack stack = w.getStack();
418 inFreeformSpace = stack != null && stack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
419 }
420
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700421 replacing |= w.mWillReplaceWindow;
422 keyguardGoingAwayWithWallpaper |= (w.mAppToken != null
423 && w.mWinAnimator.mKeyguardGoingAwayWithWallpaper);
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800424
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700425 final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800426 if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700427 if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: #" + i + "=" + w);
428 result.setWallpaperTarget(w, i);
Jorim Jaggi5c80c412016-04-19 20:03:47 -0700429 if (w == mWallpaperTarget && w.mWinAnimator.isAnimationSet()) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700430 // The current wallpaper target is animating, so we'll look behind it for
431 // another possible target and figure out what is going on later.
432 if (DEBUG_WALLPAPER) Slog.v(TAG,
433 "Win " + w + ": token animating, looking behind.");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700434 continue;
435 }
436 break;
437 } else if (w == winAnimator.mWindowDetachedWallpaper) {
438 windowDetachedI = i;
439 }
440 }
441
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700442 if (result.wallpaperTarget != null) {
443 return;
444 }
445
446 if (windowDetachedI >= 0) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700447 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700448 "Found animating detached wallpaper activity: #" + windowDetachedI + "=" + w);
449 result.setWallpaperTarget(w, windowDetachedI);
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700450 } else if (inFreeformSpace || (replacing && mWallpaperTarget != null)) {
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700451 // In freeform mode we set the wallpaper as its own target, so we don't need an
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800452 // additional window to make it visible. When we are replacing a window and there was
453 // wallpaper before replacement, we want to keep the window until the new windows fully
454 // appear and can determine the visibility, to avoid flickering.
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700455 result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700456
457 } else if (keyguardGoingAwayWithWallpaper) {
458 // If the app is executing an animation because the keyguard is going away (and the
459 // keyguard was showing the wallpaper) keep the wallpaper during the animation so it
460 // doesn't flicker out by having it be its own target.
461 result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700462 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700463 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700464
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700465 /** Updates the target wallpaper if needed and returns true if an update happened. */
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700466 private boolean updateWallpaperWindowsTarget(
467 WindowList windows, FindWallpaperTargetResult result) {
468
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700469 WindowState wallpaperTarget = result.wallpaperTarget;
470 int wallpaperTargetIndex = result.wallpaperTargetIndex;
471
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700472 if (mWallpaperTarget == wallpaperTarget
473 || (mLowerWallpaperTarget != null && mLowerWallpaperTarget == wallpaperTarget)) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700474
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700475 if (mLowerWallpaperTarget != null) {
476 // Is it time to stop animating?
477 if (!mLowerWallpaperTarget.isAnimatingLw()
478 || !mUpperWallpaperTarget.isAnimatingLw()) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700479 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700480 "No longer animating wallpaper targets!");
481 mLowerWallpaperTarget = null;
482 mUpperWallpaperTarget = null;
483 mWallpaperTarget = wallpaperTarget;
484 return true;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700485 }
486 }
487
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700488 return false;
489 }
490
491 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
492 "New wallpaper target: " + wallpaperTarget + " oldTarget: " + mWallpaperTarget);
493
494 mLowerWallpaperTarget = null;
495 mUpperWallpaperTarget = null;
496
497 WindowState oldW = mWallpaperTarget;
498 mWallpaperTarget = wallpaperTarget;
499
500 if (wallpaperTarget == null || oldW == null) {
501 return true;
502 }
503
504 // Now what is happening... if the current and new targets are animating,
505 // then we are in our super special mode!
506 boolean oldAnim = oldW.isAnimatingLw();
507 boolean foundAnim = wallpaperTarget.isAnimatingLw();
508 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
509 "New animation: " + foundAnim + " old animation: " + oldAnim);
510
511 if (!foundAnim || !oldAnim) {
512 return true;
513 }
514
515 int oldI = windows.indexOf(oldW);
516 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
517 "New i: " + wallpaperTargetIndex + " old i: " + oldI);
518
519 if (oldI < 0) {
520 return true;
521 }
522
523 final boolean newTargetHidden = wallpaperTarget.mAppToken != null
524 && wallpaperTarget.mAppToken.hiddenRequested;
525 final boolean oldTargetHidden = oldW.mAppToken != null
526 && oldW.mAppToken.hiddenRequested;
527
528 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Animating wallpapers:" + " old#" + oldI + "="
529 + oldW + " hidden=" + oldTargetHidden + " new#" + wallpaperTargetIndex + "="
530 + wallpaperTarget + " hidden=" + newTargetHidden);
531
532 // Set the upper and lower wallpaper targets correctly,
533 // and make sure that we are positioning the wallpaper below the lower.
534 if (wallpaperTargetIndex > oldI) {
535 // The new target is on top of the old one.
536 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Found target above old target.");
537 mUpperWallpaperTarget = wallpaperTarget;
538 mLowerWallpaperTarget = oldW;
539
540 wallpaperTarget = oldW;
541 wallpaperTargetIndex = oldI;
542 } else {
543 // The new target is below the old one.
544 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Found target below old target.");
545 mUpperWallpaperTarget = oldW;
546 mLowerWallpaperTarget = wallpaperTarget;
547 }
548
549 if (newTargetHidden && !oldTargetHidden) {
550 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Old wallpaper still the target.");
551 // Use the old target if new target is hidden but old target
552 // is not. If they're both hidden, still use the new target.
553 mWallpaperTarget = oldW;
554 } else if (newTargetHidden == oldTargetHidden
555 && !mService.mOpeningApps.contains(wallpaperTarget.mAppToken)
556 && (mService.mOpeningApps.contains(oldW.mAppToken)
557 || mService.mClosingApps.contains(oldW.mAppToken))) {
558 // If they're both hidden (or both not hidden), prefer the one that's currently in
559 // opening or closing app list, this allows transition selection logic to better
560 // determine the wallpaper status of opening/closing apps.
561 mWallpaperTarget = oldW;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700562 }
563
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700564 result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700565 return true;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700566 }
567
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700568 private boolean updateWallpaperWindowsTargetByLayer(WindowList windows,
569 FindWallpaperTargetResult result) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700570
571 WindowState wallpaperTarget = result.wallpaperTarget;
572 int wallpaperTargetIndex = result.wallpaperTargetIndex;
573 boolean visible = wallpaperTarget != null;
574
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700575 if (visible) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700576 // The window is visible to the compositor...but is it visible to the user?
577 // That is what the wallpaper cares about.
578 visible = isWallpaperVisible(wallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700579 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
580
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700581 // If the wallpaper target is animating, we may need to copy its layer adjustment.
582 // Only do this if we are not transferring between two wallpaper targets.
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700583 mWallpaperAnimLayerAdjustment =
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700584 (mLowerWallpaperTarget == null && wallpaperTarget.mAppToken != null)
585 ? wallpaperTarget.mAppToken.mAppAnimator.animLayerAdjustment : 0;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700586
587 final int maxLayer = (mService.mPolicy.getMaxWallpaperLayer() * TYPE_LAYER_MULTIPLIER)
588 + TYPE_LAYER_OFFSET;
589
590 // Now w is the window we are supposed to be behind... but we
591 // need to be sure to also be behind any of its attached windows,
592 // AND any starting window associated with it, AND below the
593 // maximum layer the policy allows for wallpapers.
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700594 while (wallpaperTargetIndex > 0) {
Wale Ogunwalecaa53af2016-07-17 14:50:26 -0700595 final WindowState wb = windows.get(wallpaperTargetIndex - 1);
596 final WindowState wbParentWindow = wb.getParentWindow();
597 final WindowState wallpaperParentWindow = wallpaperTarget.getParentWindow();
598 if (wb.mBaseLayer < maxLayer
599 && wbParentWindow != wallpaperTarget
600 && (wallpaperParentWindow == null || wbParentWindow != wallpaperParentWindow)
601 && (wb.mAttrs.type != TYPE_APPLICATION_STARTING
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700602 || wallpaperTarget.mToken == null
603 || wb.mToken != wallpaperTarget.mToken)) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700604 // This window is not related to the previous one in any
605 // interesting way, so stop here.
606 break;
607 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700608 wallpaperTarget = wb;
609 wallpaperTargetIndex--;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700610 }
611 } else {
612 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
613 }
614
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700615 result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
616 return visible;
617 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700618
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700619 private boolean updateWallpaperWindowsPlacement(WindowList windows,
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700620 WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible) {
621
622 // TODO(multidisplay): Wallpapers on main screen only.
623 final DisplayInfo displayInfo = mService.getDefaultDisplayContentLocked().getDisplayInfo();
624 final int dw = displayInfo.logicalWidth;
625 final int dh = displayInfo.logicalHeight;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700626
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700627 // Start stepping backwards from here, ensuring that our wallpaper windows are correctly placed.
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700628 boolean changed = false;
629 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700630 final WindowToken token = mWallpaperTokens.get(curTokenNdx);
631 changed |= token.updateWallpaperWindowsPlacement(windows, wallpaperTarget,
632 wallpaperTargetIndex, visible, dw, dh, mWallpaperAnimLayerAdjustment);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700633 }
634
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700635 return changed;
636 }
637
638 boolean adjustWallpaperWindows() {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700639 mService.mRoot.mWallpaperMayChange = false;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700640
641 final WindowList windows = mService.getDefaultWindowListLocked();
642 // First find top-most window that has asked to be on top of the wallpaper;
643 // all wallpapers go behind it.
644 findWallpaperTarget(windows, mFindResults);
645 final boolean targetChanged = updateWallpaperWindowsTarget(windows, mFindResults);
646 final boolean visible = updateWallpaperWindowsTargetByLayer(windows, mFindResults);
647 WindowState wallpaperTarget = mFindResults.wallpaperTarget;
648 int wallpaperTargetIndex = mFindResults.wallpaperTargetIndex;
649
650 if (wallpaperTarget == null && mFindResults.topWallpaper != null) {
651 // There is no wallpaper target, so it goes at the bottom.
652 // We will assume it is the same place as last time, if known.
653 wallpaperTarget = mFindResults.topWallpaper;
654 wallpaperTargetIndex = mFindResults.topWallpaperIndex + 1;
655 } else {
656 // Okay i is the position immediately above the wallpaper.
657 // Look at what is below it for later.
658 wallpaperTarget = wallpaperTargetIndex > 0
659 ? windows.get(wallpaperTargetIndex - 1) : null;
660 }
661
662 if (visible) {
663 if (mWallpaperTarget.mWallpaperX >= 0) {
664 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
665 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
666 }
667 if (mWallpaperTarget.mWallpaperY >= 0) {
668 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
669 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
670 }
671 if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
672 mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
673 }
674 if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
675 mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
676 }
677 }
678
679 final boolean changed = updateWallpaperWindowsPlacement(
680 windows, wallpaperTarget, wallpaperTargetIndex, visible);
681
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700682 if (targetChanged && DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, "New wallpaper: target="
683 + mWallpaperTarget + " lower=" + mLowerWallpaperTarget + " upper="
684 + mUpperWallpaperTarget);
685
686 return changed;
687 }
688
689 boolean processWallpaperDrawPendingTimeout() {
690 if (mWallpaperDrawState == WALLPAPER_DRAW_PENDING) {
691 mWallpaperDrawState = WALLPAPER_DRAW_TIMEOUT;
692 if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
693 "*** WALLPAPER DRAW TIMEOUT");
694 return true;
695 }
696 return false;
697 }
698
699 boolean wallpaperTransitionReady() {
700 boolean transitionReady = true;
701 boolean wallpaperReady = true;
702 for (int curTokenIndex = mWallpaperTokens.size() - 1;
703 curTokenIndex >= 0 && wallpaperReady; curTokenIndex--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700704 final WindowToken token = mWallpaperTokens.get(curTokenIndex);
705 if (token.hasVisibleNotDrawnWallpaper()) {
706 // We've told this wallpaper to be visible, but it is not drawn yet
707 wallpaperReady = false;
708 if (mWallpaperDrawState != WALLPAPER_DRAW_TIMEOUT) {
709 // wait for this wallpaper until it is drawn or timeout
710 transitionReady = false;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700711 }
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700712 if (mWallpaperDrawState == WALLPAPER_DRAW_NORMAL) {
713 mWallpaperDrawState = WALLPAPER_DRAW_PENDING;
714 mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
715 mService.mH.sendEmptyMessageDelayed(WALLPAPER_DRAW_PENDING_TIMEOUT,
716 WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION);
717 }
718 if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
719 "Wallpaper should be visible but has not been drawn yet. " +
720 "mWallpaperDrawState=" + mWallpaperDrawState);
721 break;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700722 }
723 }
724 if (wallpaperReady) {
725 mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
726 mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
727 }
728
729 return transitionReady;
730 }
731
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700732 /**
733 * Adjusts the wallpaper windows if the input display has a pending wallpaper layout or one of
734 * the opening apps should be a wallpaper target.
735 */
736 void adjustWallpaperWindowsForAppTransitionIfNeeded(
737 DisplayContent dc, ArraySet<AppWindowToken> openingApps, WindowList windows) {
738 boolean adjust = false;
739 if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
740 adjust = true;
741 } else {
742 for (int i = openingApps.size() - 1; i >= 0; --i) {
743 final AppWindowToken token = openingApps.valueAt(i);
744 if (token.windowsCanBeWallpaperTarget()) {
745 adjust = true;
746 break;
747 }
748 }
749 }
750
751 if (adjust && adjustWallpaperWindows()) {
752 mService.mLayersController.assignLayersLocked(windows);
753 dc.setLayoutNeeded();
754 }
755 }
756
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700757 void addWallpaperToken(WindowToken token) {
758 mWallpaperTokens.add(token);
759 }
760
761 void removeWallpaperToken(WindowToken token) {
762 mWallpaperTokens.remove(token);
763 }
764
765 void dump(PrintWriter pw, String prefix) {
766 pw.print(prefix); pw.print("mWallpaperTarget="); pw.println(mWallpaperTarget);
767 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
768 pw.print(prefix); pw.print("mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
769 pw.print(prefix); pw.print("mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
770 }
771 pw.print(prefix); pw.print("mLastWallpaperX="); pw.print(mLastWallpaperX);
772 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
773 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE
774 || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
775 pw.print(prefix);
776 pw.print("mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX);
777 pw.print(" mLastWallpaperDisplayOffsetY="); pw.println(mLastWallpaperDisplayOffsetY);
778 }
779 }
780
781 void dumpTokens(PrintWriter pw, String prefix, boolean dumpAll) {
782 if (!mWallpaperTokens.isEmpty()) {
783 pw.println();
784 pw.print(prefix); pw.println("Wallpaper tokens:");
785 for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
786 WindowToken token = mWallpaperTokens.get(i);
787 pw.print(prefix); pw.print("Wallpaper #"); pw.print(i);
788 pw.print(' '); pw.print(token);
789 if (dumpAll) {
790 pw.println(':');
791 token.dump(pw, " ");
792 } else {
793 pw.println();
794 }
795 }
796 }
797 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700798
799 /** Helper class for storing the results of a wallpaper target find operation. */
800 final private static class FindWallpaperTargetResult {
801 int topWallpaperIndex = 0;
802 WindowState topWallpaper = null;
803 int wallpaperTargetIndex = 0;
804 WindowState wallpaperTarget = null;
805
806 void setTopWallpaper(WindowState win, int index) {
807 topWallpaper = win;
808 topWallpaperIndex = index;
809 }
810
811 void setWallpaperTarget(WindowState win, int index) {
812 wallpaperTarget = win;
813 wallpaperTargetIndex = index;
814 }
815
816 void reset() {
817 topWallpaperIndex = 0;
818 topWallpaper = null;
819 wallpaperTargetIndex = 0;
820 wallpaperTarget = null;
821 }
822 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700823}