blob: aea8b39bd00b0751e3a1e06448b8293021d77db6 [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;
21import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
22import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
23import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
24import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080025import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
26import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
27import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
28import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
29import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
30import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
31import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
32import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
33import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070034import static com.android.server.wm.WindowManagerService.H.WALLPAPER_DRAW_PENDING_TIMEOUT;
35import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
36import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
37
38import android.os.Bundle;
39import android.os.Debug;
40import android.os.IBinder;
41import android.os.RemoteException;
42import android.os.SystemClock;
43import android.util.Slog;
44import android.view.DisplayInfo;
45import android.view.WindowManager;
46import android.view.WindowManagerPolicy;
47
48import java.io.PrintWriter;
49import java.util.ArrayList;
50
51/**
52 * Controls wallpaper windows visibility, ordering, and so on.
53 * NOTE: All methods in this class must be called with the window manager service lock held.
54 */
55class WallpaperController {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080056 private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperController" : TAG_WM;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070057 final private WindowManagerService mService;
58
59 private final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<>();
60
61 // If non-null, this is the currently visible window that is associated
62 // with the wallpaper.
63 private WindowState mWallpaperTarget = null;
64 // If non-null, we are in the middle of animating from one wallpaper target
65 // to another, and this is the lower one in Z-order.
66 private WindowState mLowerWallpaperTarget = null;
67 // If non-null, we are in the middle of animating from one wallpaper target
68 // to another, and this is the higher one in Z-order.
69 private WindowState mUpperWallpaperTarget = null;
70
71 private int mWallpaperAnimLayerAdjustment;
72
73 private float mLastWallpaperX = -1;
74 private float mLastWallpaperY = -1;
75 private float mLastWallpaperXStep = -1;
76 private float mLastWallpaperYStep = -1;
77 private int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE;
78 private int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE;
79
80 // This is set when we are waiting for a wallpaper to tell us it is done
81 // changing its scroll position.
82 WindowState mWaitingOnWallpaper;
83
84 // The last time we had a timeout when waiting for a wallpaper.
85 private long mLastWallpaperTimeoutTime;
86 // We give a wallpaper up to 150ms to finish scrolling.
87 private static final long WALLPAPER_TIMEOUT = 150;
88 // Time we wait after a timeout before trying to wait again.
89 private static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
90
91 // Set to the wallpaper window we would like to hide once the transition animations are done.
92 // This is useful in cases where we don't want the wallpaper to be hidden when the close app
93 // is a wallpaper target and is done animating out, but the opening app isn't a wallpaper
94 // target and isn't done animating in.
95 private WindowState mDeferredHideWallpaper = null;
96
97 // We give a wallpaper up to 500ms to finish drawing before playing app transitions.
98 private static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 500;
99 private static final int WALLPAPER_DRAW_NORMAL = 0;
100 private static final int WALLPAPER_DRAW_PENDING = 1;
101 private static final int WALLPAPER_DRAW_TIMEOUT = 2;
102 private int mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
103
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700104 private final FindWallpaperTargetResult mFindResults = new FindWallpaperTargetResult();
105
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700106 public WallpaperController(WindowManagerService service) {
107 mService = service;
108 }
109
110 WindowState getWallpaperTarget() {
111 return mWallpaperTarget;
112 }
113
114 WindowState getLowerWallpaperTarget() {
115 return mLowerWallpaperTarget;
116 }
117
118 WindowState getUpperWallpaperTarget() {
119 return mUpperWallpaperTarget;
120 }
121
122 boolean isWallpaperTarget(WindowState win) {
123 return win == mWallpaperTarget;
124 }
125
126 boolean isBelowWallpaperTarget(WindowState win) {
127 return mWallpaperTarget != null && mWallpaperTarget.mLayer >= win.mBaseLayer;
128 }
129
130 boolean isWallpaperVisible() {
131 return isWallpaperVisible(mWallpaperTarget);
132 }
133
134 private boolean isWallpaperVisible(WindowState wallpaperTarget) {
135 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
136 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
137 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
138 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
139 + " upper=" + mUpperWallpaperTarget
140 + " lower=" + mLowerWallpaperTarget);
141 return (wallpaperTarget != null
142 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
143 && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
144 || mUpperWallpaperTarget != null
145 || mLowerWallpaperTarget != null;
146 }
147
148 boolean isWallpaperTargetAnimating() {
Jorim Jaggi5c80c412016-04-19 20:03:47 -0700149 return mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimationSet()
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700150 && !mWallpaperTarget.mWinAnimator.isDummyAnimation();
151 }
152
153 void updateWallpaperVisibility() {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700154 final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
155 if (displayContent == null) {
156 return;
157 }
Filip Gruszczynski63a35e22015-11-05 15:38:59 -0800158 final boolean visible = isWallpaperVisible(mWallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700159 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
160 final int dw = displayInfo.logicalWidth;
161 final int dh = displayInfo.logicalHeight;
162
163 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
164 WindowToken token = mWallpaperTokens.get(curTokenNdx);
165 if (token.hidden == visible) {
166 token.hidden = !visible;
167 // Need to do a layout to ensure the wallpaper now has the
168 // correct size.
169 displayContent.layoutNeeded = true;
170 }
171
172 final WindowList windows = token.windows;
173 for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
174 WindowState wallpaper = windows.get(wallpaperNdx);
175 if (visible) {
176 updateWallpaperOffset(wallpaper, dw, dh, false);
177 }
178
179 dispatchWallpaperVisibility(wallpaper, visible);
180 }
181 }
182 }
183
184 void hideDeferredWallpapersIfNeeded() {
185 if (mDeferredHideWallpaper != null) {
186 hideWallpapers(mDeferredHideWallpaper);
187 mDeferredHideWallpaper = null;
188 }
189 }
190
191 void hideWallpapers(final WindowState winGoingAway) {
192 if (mWallpaperTarget != null
193 && (mWallpaperTarget != winGoingAway || mLowerWallpaperTarget != null)) {
194 return;
195 }
196 if (mService.mAppTransition.isRunning()) {
197 // Defer hiding the wallpaper when app transition is running until the animations
198 // are done.
199 mDeferredHideWallpaper = winGoingAway;
200 return;
201 }
202
203 final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway);
204 for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
205 final WindowToken token = mWallpaperTokens.get(i);
206 for (int j = token.windows.size() - 1; j >= 0; j--) {
207 final WindowState wallpaper = token.windows.get(j);
208 final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
209 if (!winAnimator.mLastHidden || wasDeferred) {
Filip Gruszczynski63a35e22015-11-05 15:38:59 -0800210 winAnimator.hide("hideWallpapers");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700211 dispatchWallpaperVisibility(wallpaper, false);
212 final DisplayContent displayContent = wallpaper.getDisplayContent();
213 if (displayContent != null) {
214 displayContent.pendingLayoutChanges |=
215 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
216 }
217 }
218 }
219 if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
220 + " from " + winGoingAway + " target=" + mWallpaperTarget + " lower="
221 + mLowerWallpaperTarget + "\n" + Debug.getCallers(5, " "));
222 token.hidden = true;
223 }
224 }
225
226 /**
227 * Check wallpaper for visibility change and notify window if so.
228 * @param wallpaper The wallpaper to test and notify.
229 * @param visible Current visibility.
230 */
231 void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
232 // Only send notification if the visibility actually changed and we are not trying to hide
233 // the wallpaper when we are deferring hiding of the wallpaper.
234 if (wallpaper.mWallpaperVisible != visible
235 && (mDeferredHideWallpaper == null || visible)) {
236 wallpaper.mWallpaperVisible = visible;
237 try {
238 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
239 "Updating vis of wallpaper " + wallpaper
240 + ": " + visible + " from:\n" + Debug.getCallers(4, " "));
241 wallpaper.mClient.dispatchAppVisibility(visible);
242 } catch (RemoteException e) {
243 }
244 }
245 }
246
247 boolean updateWallpaperOffset(WindowState wallpaperWin, int dw, int dh, boolean sync) {
248 boolean rawChanged = false;
Winson4b4ba902016-07-27 19:45:52 -0700249 // Set the default wallpaper x-offset to either edge of the screen (depending on RTL), to
250 // match the behavior of most Launchers
251 float defaultWallpaperX = wallpaperWin.isRtl() ? 1f : 0f;
252 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : defaultWallpaperX;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700253 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
254 int availw = wallpaperWin.mFrame.right - wallpaperWin.mFrame.left - dw;
255 int offset = availw > 0 ? -(int)(availw * wpx + .5f) : 0;
256 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
257 offset += mLastWallpaperDisplayOffsetX;
258 }
259 boolean changed = wallpaperWin.mXOffset != offset;
260 if (changed) {
261 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " x: " + offset);
262 wallpaperWin.mXOffset = offset;
263 }
264 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
265 wallpaperWin.mWallpaperX = wpx;
266 wallpaperWin.mWallpaperXStep = wpxs;
267 rawChanged = true;
268 }
269
270 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
271 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
272 int availh = wallpaperWin.mFrame.bottom - wallpaperWin.mFrame.top - dh;
273 offset = availh > 0 ? -(int)(availh * wpy + .5f) : 0;
274 if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
275 offset += mLastWallpaperDisplayOffsetY;
276 }
277 if (wallpaperWin.mYOffset != offset) {
278 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " y: " + offset);
279 changed = true;
280 wallpaperWin.mYOffset = offset;
281 }
282 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
283 wallpaperWin.mWallpaperY = wpy;
284 wallpaperWin.mWallpaperYStep = wpys;
285 rawChanged = true;
286 }
287
288 if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
289 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
290 try {
291 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
292 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
293 + " y=" + wallpaperWin.mWallpaperY);
294 if (sync) {
295 mWaitingOnWallpaper = wallpaperWin;
296 }
297 wallpaperWin.mClient.dispatchWallpaperOffsets(
298 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
299 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
300 if (sync) {
301 if (mWaitingOnWallpaper != null) {
302 long start = SystemClock.uptimeMillis();
303 if ((mLastWallpaperTimeoutTime + WALLPAPER_TIMEOUT_RECOVERY)
304 < start) {
305 try {
306 if (DEBUG_WALLPAPER) Slog.v(TAG,
307 "Waiting for offset complete...");
308 mService.mWindowMap.wait(WALLPAPER_TIMEOUT);
309 } catch (InterruptedException e) {
310 }
311 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
312 if ((start + WALLPAPER_TIMEOUT) < SystemClock.uptimeMillis()) {
313 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
314 + wallpaperWin);
315 mLastWallpaperTimeoutTime = start;
316 }
317 }
318 mWaitingOnWallpaper = null;
319 }
320 }
321 } catch (RemoteException e) {
322 }
323 }
324
325 return changed;
326 }
327
328 void setWindowWallpaperPosition(
329 WindowState window, float x, float y, float xStep, float yStep) {
330 if (window.mWallpaperX != x || window.mWallpaperY != y) {
331 window.mWallpaperX = x;
332 window.mWallpaperY = y;
333 window.mWallpaperXStep = xStep;
334 window.mWallpaperYStep = yStep;
335 updateWallpaperOffsetLocked(window, true);
336 }
337 }
338
339 void setWindowWallpaperDisplayOffset(WindowState window, int x, int y) {
340 if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y) {
341 window.mWallpaperDisplayOffsetX = x;
342 window.mWallpaperDisplayOffsetY = y;
343 updateWallpaperOffsetLocked(window, true);
344 }
345 }
346
347 Bundle sendWindowWallpaperCommand(
348 WindowState window, String action, int x, int y, int z, Bundle extras, boolean sync) {
Erik Wolsheimerb608d282016-10-20 21:09:44 -0700349
350 // HACK(ewol): Custom whitelist for Wear Home app, to allow it to update the wallpaper
351 // regardless of what window is targeted.
352 // http://b/32172459
353 final boolean hackWearWhitelisted = (window != null) && (window.mAttrs != null)
354 && "com.google.android.wearable.app".equals(window.mAttrs.packageName);
355
356 if (hackWearWhitelisted
357 || window == mWallpaperTarget
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700358 || window == mLowerWallpaperTarget
359 || window == mUpperWallpaperTarget) {
360 boolean doWait = sync;
361 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
362 final WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
363 for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
364 WindowState wallpaper = windows.get(wallpaperNdx);
365 try {
366 wallpaper.mClient.dispatchWallpaperCommand(action,
367 x, y, z, extras, sync);
368 // We only want to be synchronous with one wallpaper.
369 sync = false;
370 } catch (RemoteException e) {
371 }
372 }
373 }
374
375 if (doWait) {
376 // TODO: Need to wait for result.
377 }
378 }
379
380 return null;
381 }
382
383 void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
384 final DisplayContent displayContent = changingTarget.getDisplayContent();
385 if (displayContent == null) {
386 return;
387 }
388 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
389 final int dw = displayInfo.logicalWidth;
390 final int dh = displayInfo.logicalHeight;
391
392 WindowState target = mWallpaperTarget;
393 if (target != null) {
394 if (target.mWallpaperX >= 0) {
395 mLastWallpaperX = target.mWallpaperX;
396 } else if (changingTarget.mWallpaperX >= 0) {
397 mLastWallpaperX = changingTarget.mWallpaperX;
398 }
399 if (target.mWallpaperY >= 0) {
400 mLastWallpaperY = target.mWallpaperY;
401 } else if (changingTarget.mWallpaperY >= 0) {
402 mLastWallpaperY = changingTarget.mWallpaperY;
403 }
404 if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
405 mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
406 } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
407 mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
408 }
409 if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
410 mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
411 } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
412 mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
413 }
414 if (target.mWallpaperXStep >= 0) {
415 mLastWallpaperXStep = target.mWallpaperXStep;
416 } else if (changingTarget.mWallpaperXStep >= 0) {
417 mLastWallpaperXStep = changingTarget.mWallpaperXStep;
418 }
419 if (target.mWallpaperYStep >= 0) {
420 mLastWallpaperYStep = target.mWallpaperYStep;
421 } else if (changingTarget.mWallpaperYStep >= 0) {
422 mLastWallpaperYStep = changingTarget.mWallpaperYStep;
423 }
424 }
425
426 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
427 WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
428 for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
429 WindowState wallpaper = windows.get(wallpaperNdx);
430 if (updateWallpaperOffset(wallpaper, dw, dh, sync)) {
431 WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
432 winAnimator.computeShownFrameLocked();
433 // No need to lay out the windows - we can just set the wallpaper position
434 // directly.
Filip Gruszczynski2a6a2c22015-10-14 12:00:53 -0700435 winAnimator.setWallpaperOffset(wallpaper.mShownPosition);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700436 // We only want to be synchronous with one wallpaper.
437 sync = false;
438 }
439 }
440 }
441 }
442
443 void clearLastWallpaperTimeoutTime() {
444 mLastWallpaperTimeoutTime = 0;
445 }
446
447 void wallpaperCommandComplete(IBinder window) {
448 if (mWaitingOnWallpaper != null &&
449 mWaitingOnWallpaper.mClient.asBinder() == window) {
450 mWaitingOnWallpaper = null;
451 mService.mWindowMap.notifyAll();
452 }
453 }
454
455 void wallpaperOffsetsComplete(IBinder window) {
456 if (mWaitingOnWallpaper != null &&
457 mWaitingOnWallpaper.mClient.asBinder() == window) {
458 mWaitingOnWallpaper = null;
459 mService.mWindowMap.notifyAll();
460 }
461 }
462
463 int getAnimLayerAdjustment() {
464 return mWallpaperAnimLayerAdjustment;
465 }
466
467 void setAnimLayerAdjustment(WindowState win, int adj) {
468 if (win != mWallpaperTarget || mLowerWallpaperTarget != null) {
469 return;
470 }
471
472 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Setting wallpaper layer adj to " + adj);
473 mWallpaperAnimLayerAdjustment = adj;
474 for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
475 WindowList windows = mWallpaperTokens.get(i).windows;
476 for (int j = windows.size() - 1; j >= 0; j--) {
477 WindowState wallpaper = windows.get(j);
478 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
479 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
480 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
481 }
482 }
483 }
484
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700485 private void findWallpaperTarget(WindowList windows, FindWallpaperTargetResult result) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700486 final WindowAnimator winAnimator = mService.mAnimator;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700487 result.reset();
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700488 WindowState w = null;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700489 int windowDetachedI = -1;
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700490 boolean resetTopWallpaper = false;
491 boolean inFreeformSpace = false;
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800492 boolean replacing = false;
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700493 boolean keyguardGoingAwayWithWallpaper = false;
494
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700495 for (int i = windows.size() - 1; i >= 0; i--) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700496 w = windows.get(i);
497 if ((w.mAttrs.type == TYPE_WALLPAPER)) {
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700498 if (result.topWallpaper == null || resetTopWallpaper) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700499 result.setTopWallpaper(w, i);
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700500 resetTopWallpaper = false;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700501 }
502 continue;
503 }
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700504 resetTopWallpaper = true;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700505 if (w != winAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
506 // If this window's app token is hidden and not animating,
507 // it is of no interest to us.
508 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
509 if (DEBUG_WALLPAPER) Slog.v(TAG,
510 "Skipping hidden and not animating token: " + w);
511 continue;
512 }
513 }
514 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
515 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
516
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700517 if (!inFreeformSpace) {
518 TaskStack stack = w.getStack();
519 inFreeformSpace = stack != null && stack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
520 }
521
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700522 replacing |= w.mWillReplaceWindow;
523 keyguardGoingAwayWithWallpaper |= (w.mAppToken != null
524 && w.mWinAnimator.mKeyguardGoingAwayWithWallpaper);
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800525
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700526 final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800527 if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700528 if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: #" + i + "=" + w);
529 result.setWallpaperTarget(w, i);
Jorim Jaggi5c80c412016-04-19 20:03:47 -0700530 if (w == mWallpaperTarget && w.mWinAnimator.isAnimationSet()) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700531 // The current wallpaper target is animating, so we'll look behind it for
532 // another possible target and figure out what is going on later.
533 if (DEBUG_WALLPAPER) Slog.v(TAG,
534 "Win " + w + ": token animating, looking behind.");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700535 continue;
536 }
537 break;
538 } else if (w == winAnimator.mWindowDetachedWallpaper) {
539 windowDetachedI = i;
540 }
541 }
542
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700543 if (result.wallpaperTarget != null) {
544 return;
545 }
546
547 if (windowDetachedI >= 0) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700548 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700549 "Found animating detached wallpaper activity: #" + windowDetachedI + "=" + w);
550 result.setWallpaperTarget(w, windowDetachedI);
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700551 } else if (inFreeformSpace || (replacing && mWallpaperTarget != null)) {
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700552 // In freeform mode we set the wallpaper as its own target, so we don't need an
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800553 // additional window to make it visible. When we are replacing a window and there was
554 // wallpaper before replacement, we want to keep the window until the new windows fully
555 // appear and can determine the visibility, to avoid flickering.
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700556 result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700557
558 } else if (keyguardGoingAwayWithWallpaper) {
559 // If the app is executing an animation because the keyguard is going away (and the
560 // keyguard was showing the wallpaper) keep the wallpaper during the animation so it
561 // doesn't flicker out by having it be its own target.
562 result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700563 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700564 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700565
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700566 private boolean updateWallpaperWindowsTarget(
567 WindowList windows, FindWallpaperTargetResult result) {
568
569 boolean targetChanged = false;
570 WindowState wallpaperTarget = result.wallpaperTarget;
571 int wallpaperTargetIndex = result.wallpaperTargetIndex;
572
573 if (mWallpaperTarget != wallpaperTarget
574 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != wallpaperTarget)) {
575 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
576 "New wallpaper target: " + wallpaperTarget + " oldTarget: " + mWallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700577
578 mLowerWallpaperTarget = null;
579 mUpperWallpaperTarget = null;
580
581 WindowState oldW = mWallpaperTarget;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700582 mWallpaperTarget = wallpaperTarget;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700583 targetChanged = true;
584
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700585 // Now what is happening... if the current and new targets are animating,
586 // then we are in our super special mode!
587 if (wallpaperTarget != null && oldW != null) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700588 boolean oldAnim = oldW.isAnimatingLw();
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700589 boolean foundAnim = wallpaperTarget.isAnimatingLw();
590 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
591 "New animation: " + foundAnim + " old animation: " + oldAnim);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700592 if (foundAnim && oldAnim) {
593 int oldI = windows.indexOf(oldW);
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700594 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
595 "New i: " + wallpaperTargetIndex + " old i: " + oldI);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700596 if (oldI >= 0) {
Chong Zhangb0d26702016-08-12 16:03:29 -0700597 final boolean newTargetHidden =
598 wallpaperTarget.mAppToken != null && wallpaperTarget.mAppToken.hiddenRequested;
599 final boolean oldTargetHidden =
600 oldW.mAppToken != null && oldW.mAppToken.hiddenRequested;
601 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Animating wallpapers:"
602 + " old#" + oldI + "=" + oldW + " hidden=" + oldTargetHidden
603 + " new#" + wallpaperTargetIndex + "=" + wallpaperTarget
604 + " hidden=" + newTargetHidden);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700605
Chong Zhangf96cb3c2016-08-15 11:09:29 -0700606 // Set the upper and lower wallpaper targets correctly,
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700607 // and make sure that we are positioning the wallpaper below the lower.
Chong Zhangf96cb3c2016-08-15 11:09:29 -0700608 if (wallpaperTargetIndex > oldI) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700609 // The new target is on top of the old one.
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700610 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
611 "Found target above old target.");
612 mUpperWallpaperTarget = wallpaperTarget;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700613 mLowerWallpaperTarget = oldW;
Chong Zhangb0d26702016-08-12 16:03:29 -0700614
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700615 wallpaperTarget = oldW;
616 wallpaperTargetIndex = oldI;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700617 } else {
618 // The new target is below the old one.
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700619 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
620 "Found target below old target.");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700621 mUpperWallpaperTarget = oldW;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700622 mLowerWallpaperTarget = wallpaperTarget;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700623 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700624 if (newTargetHidden && !oldTargetHidden) {
Chong Zhangf96cb3c2016-08-15 11:09:29 -0700625 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
626 "Old wallpaper still the target.");
Chong Zhangb0d26702016-08-12 16:03:29 -0700627 // Use the old target if new target is hidden but old target
628 // is not. If they're both hidden, still use the new target.
Chong Zhangf96cb3c2016-08-15 11:09:29 -0700629 mWallpaperTarget = oldW;
Chong Zhangb0d26702016-08-12 16:03:29 -0700630 } else if (newTargetHidden == oldTargetHidden
631 && !mService.mOpeningApps.contains(wallpaperTarget.mAppToken)
632 && (mService.mOpeningApps.contains(oldW.mAppToken)
633 || mService.mClosingApps.contains(oldW.mAppToken))) {
634 // If they're both hidden (or both not hidden), prefer the one that's
635 // currently in opening or closing app list, this allows transition
636 // selection logic to better determine the wallpaper status of
637 // opening/closing apps.
638 mWallpaperTarget = oldW;
Chong Zhangf96cb3c2016-08-15 11:09:29 -0700639 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700640 }
641 }
642 }
643
644 } else if (mLowerWallpaperTarget != null) {
645 // Is it time to stop animating?
646 if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700647 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "No longer animating wallpaper targets!");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700648 mLowerWallpaperTarget = null;
649 mUpperWallpaperTarget = null;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700650 mWallpaperTarget = wallpaperTarget;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700651 targetChanged = true;
652 }
653 }
654
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700655 result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
656 return targetChanged;
657 }
658
659 boolean updateWallpaperWindowsTargetByLayer(
660 WindowList windows, FindWallpaperTargetResult result) {
661
662 WindowState wallpaperTarget = result.wallpaperTarget;
663 int wallpaperTargetIndex = result.wallpaperTargetIndex;
664 boolean visible = wallpaperTarget != null;
665
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700666 if (visible) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700667 // The window is visible to the compositor...but is it visible to the user?
668 // That is what the wallpaper cares about.
669 visible = isWallpaperVisible(wallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700670 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
671
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700672 // If the wallpaper target is animating, we may need to copy its layer adjustment.
673 // Only do this if we are not transferring between two wallpaper targets.
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700674 mWallpaperAnimLayerAdjustment =
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700675 (mLowerWallpaperTarget == null && wallpaperTarget.mAppToken != null)
676 ? wallpaperTarget.mAppToken.mAppAnimator.animLayerAdjustment : 0;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700677
678 final int maxLayer = (mService.mPolicy.getMaxWallpaperLayer() * TYPE_LAYER_MULTIPLIER)
679 + TYPE_LAYER_OFFSET;
680
681 // Now w is the window we are supposed to be behind... but we
682 // need to be sure to also be behind any of its attached windows,
683 // AND any starting window associated with it, AND below the
684 // maximum layer the policy allows for wallpapers.
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700685 while (wallpaperTargetIndex > 0) {
686 WindowState wb = windows.get(wallpaperTargetIndex - 1);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700687 if (wb.mBaseLayer < maxLayer &&
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700688 wb.mAttachedWindow != wallpaperTarget &&
689 (wallpaperTarget.mAttachedWindow == null ||
690 wb.mAttachedWindow != wallpaperTarget.mAttachedWindow) &&
691 (wb.mAttrs.type != TYPE_APPLICATION_STARTING
692 || wallpaperTarget.mToken == null
693 || wb.mToken != wallpaperTarget.mToken)) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700694 // This window is not related to the previous one in any
695 // interesting way, so stop here.
696 break;
697 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700698 wallpaperTarget = wb;
699 wallpaperTargetIndex--;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700700 }
701 } else {
702 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
703 }
704
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700705 result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
706 return visible;
707 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700708
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700709 boolean updateWallpaperWindowsPlacement(WindowList windows,
710 WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible) {
711
712 // TODO(multidisplay): Wallpapers on main screen only.
713 final DisplayInfo displayInfo = mService.getDefaultDisplayContentLocked().getDisplayInfo();
714 final int dw = displayInfo.logicalWidth;
715 final int dh = displayInfo.logicalHeight;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700716
717 // Start stepping backwards from here, ensuring that our wallpaper windows
718 // are correctly placed.
719 boolean changed = false;
720 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
721 WindowToken token = mWallpaperTokens.get(curTokenNdx);
722 if (token.hidden == visible) {
723 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
724 "Wallpaper token " + token + " hidden=" + !visible);
725 token.hidden = !visible;
726 // Need to do a layout to ensure the wallpaper now has the correct size.
727 mService.getDefaultDisplayContentLocked().layoutNeeded = true;
728 }
729
730 final WindowList tokenWindows = token.windows;
731 for (int wallpaperNdx = tokenWindows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
732 WindowState wallpaper = tokenWindows.get(wallpaperNdx);
733
734 if (visible) {
735 updateWallpaperOffset(wallpaper, dw, dh, false);
736 }
737
738 // First, make sure the client has the current visibility state.
739 dispatchWallpaperVisibility(wallpaper, visible);
740
741 wallpaper.mWinAnimator.mAnimLayer =
742 wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
743 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
744 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
745
746 // First, if this window is at the current index, then all is well.
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700747 if (wallpaper == wallpaperTarget) {
748 wallpaperTargetIndex--;
749 wallpaperTarget = wallpaperTargetIndex > 0
750 ? windows.get(wallpaperTargetIndex - 1) : null;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700751 continue;
752 }
753
754 // The window didn't match... the current wallpaper window,
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700755 // wherever it is, is in the wrong place, so make sure it is not in the list.
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700756 int oldIndex = windows.indexOf(wallpaper);
757 if (oldIndex >= 0) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700758 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
759 "Wallpaper removing at " + oldIndex + ": " + wallpaper);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700760 windows.remove(oldIndex);
761 mService.mWindowsChanged = true;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700762 if (oldIndex < wallpaperTargetIndex) {
763 wallpaperTargetIndex--;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700764 }
765 }
766
767 // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
Jorim Jaggi6626f542016-08-22 13:08:44 -0700768 // layer. For keyguard over wallpaper put the wallpaper under the lowest window that
769 // is currently on screen, i.e. not hidden by policy.
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700770 int insertionIndex = 0;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700771 if (visible && wallpaperTarget != null) {
772 final int type = wallpaperTarget.mAttrs.type;
773 final int privateFlags = wallpaperTarget.mAttrs.privateFlags;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700774 if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0
775 || type == TYPE_KEYGUARD_SCRIM) {
Jorim Jaggi6626f542016-08-22 13:08:44 -0700776 insertionIndex = Math.min(windows.indexOf(wallpaperTarget),
777 findLowestWindowOnScreen(windows));
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700778 }
779 }
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -0700780 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT
781 || (DEBUG_ADD_REMOVE && oldIndex != insertionIndex)) Slog.v(TAG,
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700782 "Moving wallpaper " + wallpaper
783 + " from " + oldIndex + " to " + insertionIndex);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700784
785 windows.add(insertionIndex, wallpaper);
786 mService.mWindowsChanged = true;
787 changed = true;
788 }
789 }
790
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700791 return changed;
792 }
793
Jorim Jaggi6626f542016-08-22 13:08:44 -0700794 /**
795 * @return The index in {@param windows} of the lowest window that is currently on screen and
796 * not hidden by the policy.
797 */
798 private int findLowestWindowOnScreen(WindowList windows) {
799 final int size = windows.size();
800 for (int index = 0; index < size; index++) {
801 final WindowState win = windows.get(index);
802 if (win.isOnScreen()) {
803 return index;
804 }
805 }
806 return Integer.MAX_VALUE;
807 }
808
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700809 boolean adjustWallpaperWindows() {
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700810 mService.mWindowPlacerLocked.mWallpaperMayChange = false;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700811
812 final WindowList windows = mService.getDefaultWindowListLocked();
813 // First find top-most window that has asked to be on top of the wallpaper;
814 // all wallpapers go behind it.
815 findWallpaperTarget(windows, mFindResults);
816 final boolean targetChanged = updateWallpaperWindowsTarget(windows, mFindResults);
817 final boolean visible = updateWallpaperWindowsTargetByLayer(windows, mFindResults);
818 WindowState wallpaperTarget = mFindResults.wallpaperTarget;
819 int wallpaperTargetIndex = mFindResults.wallpaperTargetIndex;
820
821 if (wallpaperTarget == null && mFindResults.topWallpaper != null) {
822 // There is no wallpaper target, so it goes at the bottom.
823 // We will assume it is the same place as last time, if known.
824 wallpaperTarget = mFindResults.topWallpaper;
825 wallpaperTargetIndex = mFindResults.topWallpaperIndex + 1;
826 } else {
827 // Okay i is the position immediately above the wallpaper.
828 // Look at what is below it for later.
829 wallpaperTarget = wallpaperTargetIndex > 0
830 ? windows.get(wallpaperTargetIndex - 1) : null;
831 }
832
833 if (visible) {
834 if (mWallpaperTarget.mWallpaperX >= 0) {
835 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
836 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
837 }
838 if (mWallpaperTarget.mWallpaperY >= 0) {
839 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
840 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
841 }
842 if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
843 mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
844 }
845 if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
846 mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
847 }
848 }
849
850 final boolean changed = updateWallpaperWindowsPlacement(
851 windows, wallpaperTarget, wallpaperTargetIndex, visible);
852
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700853 if (targetChanged && DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, "New wallpaper: target="
854 + mWallpaperTarget + " lower=" + mLowerWallpaperTarget + " upper="
855 + mUpperWallpaperTarget);
856
857 return changed;
858 }
859
860 boolean processWallpaperDrawPendingTimeout() {
861 if (mWallpaperDrawState == WALLPAPER_DRAW_PENDING) {
862 mWallpaperDrawState = WALLPAPER_DRAW_TIMEOUT;
863 if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
864 "*** WALLPAPER DRAW TIMEOUT");
865 return true;
866 }
867 return false;
868 }
869
870 boolean wallpaperTransitionReady() {
871 boolean transitionReady = true;
872 boolean wallpaperReady = true;
873 for (int curTokenIndex = mWallpaperTokens.size() - 1;
874 curTokenIndex >= 0 && wallpaperReady; curTokenIndex--) {
875 WindowToken token = mWallpaperTokens.get(curTokenIndex);
876 for (int curWallpaperIndex = token.windows.size() - 1; curWallpaperIndex >= 0;
877 curWallpaperIndex--) {
878 WindowState wallpaper = token.windows.get(curWallpaperIndex);
879 if (wallpaper.mWallpaperVisible && !wallpaper.isDrawnLw()) {
880 // We've told this wallpaper to be visible, but it is not drawn yet
881 wallpaperReady = false;
882 if (mWallpaperDrawState != WALLPAPER_DRAW_TIMEOUT) {
883 // wait for this wallpaper until it is drawn or timeout
884 transitionReady = false;
885 }
886 if (mWallpaperDrawState == WALLPAPER_DRAW_NORMAL) {
887 mWallpaperDrawState = WALLPAPER_DRAW_PENDING;
888 mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
889 mService.mH.sendEmptyMessageDelayed(WALLPAPER_DRAW_PENDING_TIMEOUT,
890 WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION);
891 }
892 if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
893 "Wallpaper should be visible but has not been drawn yet. " +
894 "mWallpaperDrawState=" + mWallpaperDrawState);
895 break;
896 }
897 }
898 }
899 if (wallpaperReady) {
900 mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
901 mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
902 }
903
904 return transitionReady;
905 }
906
907 void addWallpaperToken(WindowToken token) {
908 mWallpaperTokens.add(token);
909 }
910
911 void removeWallpaperToken(WindowToken token) {
912 mWallpaperTokens.remove(token);
913 }
914
915 void dump(PrintWriter pw, String prefix) {
916 pw.print(prefix); pw.print("mWallpaperTarget="); pw.println(mWallpaperTarget);
917 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
918 pw.print(prefix); pw.print("mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
919 pw.print(prefix); pw.print("mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
920 }
921 pw.print(prefix); pw.print("mLastWallpaperX="); pw.print(mLastWallpaperX);
922 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
923 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE
924 || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
925 pw.print(prefix);
926 pw.print("mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX);
927 pw.print(" mLastWallpaperDisplayOffsetY="); pw.println(mLastWallpaperDisplayOffsetY);
928 }
929 }
930
931 void dumpTokens(PrintWriter pw, String prefix, boolean dumpAll) {
932 if (!mWallpaperTokens.isEmpty()) {
933 pw.println();
934 pw.print(prefix); pw.println("Wallpaper tokens:");
935 for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
936 WindowToken token = mWallpaperTokens.get(i);
937 pw.print(prefix); pw.print("Wallpaper #"); pw.print(i);
938 pw.print(' '); pw.print(token);
939 if (dumpAll) {
940 pw.println(':');
941 token.dump(pw, " ");
942 } else {
943 pw.println();
944 }
945 }
946 }
947 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700948
949 /** Helper class for storing the results of a wallpaper target find operation. */
950 final private static class FindWallpaperTargetResult {
951 int topWallpaperIndex = 0;
952 WindowState topWallpaper = null;
953 int wallpaperTargetIndex = 0;
954 WindowState wallpaperTarget = null;
955
956 void setTopWallpaper(WindowState win, int index) {
957 topWallpaper = win;
958 topWallpaperIndex = index;
959 }
960
961 void setWallpaperTarget(WindowState win, int index) {
962 wallpaperTarget = win;
963 wallpaperTargetIndex = index;
964 }
965
966 void reset() {
967 topWallpaperIndex = 0;
968 topWallpaper = null;
969 wallpaperTargetIndex = 0;
970 wallpaperTarget = null;
971 }
972 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700973}