blob: 58439eb6da1c71f8a5f3a84f5684c570c2b0ad41 [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;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080029import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
30import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
31import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
32import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070033import static com.android.server.wm.WindowManagerService.H.WALLPAPER_DRAW_PENDING_TIMEOUT;
34import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
35import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
36
37import android.os.Bundle;
38import android.os.Debug;
39import android.os.IBinder;
40import android.os.RemoteException;
41import android.os.SystemClock;
42import android.util.Slog;
43import android.view.DisplayInfo;
44import android.view.WindowManager;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070045
46import java.io.PrintWriter;
47import java.util.ArrayList;
48
49/**
50 * Controls wallpaper windows visibility, ordering, and so on.
51 * NOTE: All methods in this class must be called with the window manager service lock held.
52 */
53class WallpaperController {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080054 private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperController" : TAG_WM;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070055 final private WindowManagerService mService;
56
57 private final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<>();
58
59 // If non-null, this is the currently visible window that is associated
60 // with the wallpaper.
61 private WindowState mWallpaperTarget = null;
62 // If non-null, we are in the middle of animating from one wallpaper target
63 // to another, and this is the lower one in Z-order.
64 private WindowState mLowerWallpaperTarget = null;
65 // If non-null, we are in the middle of animating from one wallpaper target
66 // to another, and this is the higher one in Z-order.
67 private WindowState mUpperWallpaperTarget = null;
68
69 private int mWallpaperAnimLayerAdjustment;
70
71 private float mLastWallpaperX = -1;
72 private float mLastWallpaperY = -1;
73 private float mLastWallpaperXStep = -1;
74 private float mLastWallpaperYStep = -1;
75 private int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE;
76 private int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE;
77
78 // This is set when we are waiting for a wallpaper to tell us it is done
79 // changing its scroll position.
80 WindowState mWaitingOnWallpaper;
81
82 // The last time we had a timeout when waiting for a wallpaper.
83 private long mLastWallpaperTimeoutTime;
84 // We give a wallpaper up to 150ms to finish scrolling.
85 private static final long WALLPAPER_TIMEOUT = 150;
86 // Time we wait after a timeout before trying to wait again.
87 private static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
88
89 // Set to the wallpaper window we would like to hide once the transition animations are done.
90 // This is useful in cases where we don't want the wallpaper to be hidden when the close app
91 // is a wallpaper target and is done animating out, but the opening app isn't a wallpaper
92 // target and isn't done animating in.
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070093 WindowState mDeferredHideWallpaper = null;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070094
95 // We give a wallpaper up to 500ms to finish drawing before playing app transitions.
96 private static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 500;
97 private static final int WALLPAPER_DRAW_NORMAL = 0;
98 private static final int WALLPAPER_DRAW_PENDING = 1;
99 private static final int WALLPAPER_DRAW_TIMEOUT = 2;
100 private int mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
101
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700102 private final FindWallpaperTargetResult mFindResults = new FindWallpaperTargetResult();
103
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700104 public WallpaperController(WindowManagerService service) {
105 mService = service;
106 }
107
108 WindowState getWallpaperTarget() {
109 return mWallpaperTarget;
110 }
111
112 WindowState getLowerWallpaperTarget() {
113 return mLowerWallpaperTarget;
114 }
115
116 WindowState getUpperWallpaperTarget() {
117 return mUpperWallpaperTarget;
118 }
119
120 boolean isWallpaperTarget(WindowState win) {
121 return win == mWallpaperTarget;
122 }
123
124 boolean isBelowWallpaperTarget(WindowState win) {
125 return mWallpaperTarget != null && mWallpaperTarget.mLayer >= win.mBaseLayer;
126 }
127
128 boolean isWallpaperVisible() {
129 return isWallpaperVisible(mWallpaperTarget);
130 }
131
132 private boolean isWallpaperVisible(WindowState wallpaperTarget) {
133 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
134 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
135 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
136 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
137 + " upper=" + mUpperWallpaperTarget
138 + " lower=" + mLowerWallpaperTarget);
139 return (wallpaperTarget != null
140 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
141 && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
142 || mUpperWallpaperTarget != null
143 || mLowerWallpaperTarget != null;
144 }
145
146 boolean isWallpaperTargetAnimating() {
Jorim Jaggi5c80c412016-04-19 20:03:47 -0700147 return mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimationSet()
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700148 && !mWallpaperTarget.mWinAnimator.isDummyAnimation();
149 }
150
151 void updateWallpaperVisibility() {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700152 final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
153 if (displayContent == null) {
154 return;
155 }
Filip Gruszczynski63a35e22015-11-05 15:38:59 -0800156 final boolean visible = isWallpaperVisible(mWallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700157 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
158 final int dw = displayInfo.logicalWidth;
159 final int dh = displayInfo.logicalHeight;
160
161 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700162 final WindowToken token = mWallpaperTokens.get(curTokenNdx);
163 token.updateWallpaperVisibility(dw, dh, visible, displayContent);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700164 }
165 }
166
167 void hideDeferredWallpapersIfNeeded() {
168 if (mDeferredHideWallpaper != null) {
169 hideWallpapers(mDeferredHideWallpaper);
170 mDeferredHideWallpaper = null;
171 }
172 }
173
174 void hideWallpapers(final WindowState winGoingAway) {
175 if (mWallpaperTarget != null
176 && (mWallpaperTarget != winGoingAway || mLowerWallpaperTarget != null)) {
177 return;
178 }
179 if (mService.mAppTransition.isRunning()) {
180 // Defer hiding the wallpaper when app transition is running until the animations
181 // are done.
182 mDeferredHideWallpaper = winGoingAway;
183 return;
184 }
185
186 final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway);
187 for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
188 final WindowToken token = mWallpaperTokens.get(i);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700189 token.hideWallpaperToken(wasDeferred, "hideWallpapers");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700190 if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
191 + " from " + winGoingAway + " target=" + mWallpaperTarget + " lower="
192 + mLowerWallpaperTarget + "\n" + Debug.getCallers(5, " "));
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700193 }
194 }
195
196 boolean updateWallpaperOffset(WindowState wallpaperWin, int dw, int dh, boolean sync) {
197 boolean rawChanged = false;
Winson4b4ba902016-07-27 19:45:52 -0700198 // Set the default wallpaper x-offset to either edge of the screen (depending on RTL), to
199 // match the behavior of most Launchers
200 float defaultWallpaperX = wallpaperWin.isRtl() ? 1f : 0f;
201 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : defaultWallpaperX;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700202 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
203 int availw = wallpaperWin.mFrame.right - wallpaperWin.mFrame.left - dw;
204 int offset = availw > 0 ? -(int)(availw * wpx + .5f) : 0;
205 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
206 offset += mLastWallpaperDisplayOffsetX;
207 }
208 boolean changed = wallpaperWin.mXOffset != offset;
209 if (changed) {
210 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " x: " + offset);
211 wallpaperWin.mXOffset = offset;
212 }
213 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
214 wallpaperWin.mWallpaperX = wpx;
215 wallpaperWin.mWallpaperXStep = wpxs;
216 rawChanged = true;
217 }
218
219 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
220 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
221 int availh = wallpaperWin.mFrame.bottom - wallpaperWin.mFrame.top - dh;
222 offset = availh > 0 ? -(int)(availh * wpy + .5f) : 0;
223 if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
224 offset += mLastWallpaperDisplayOffsetY;
225 }
226 if (wallpaperWin.mYOffset != offset) {
227 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " y: " + offset);
228 changed = true;
229 wallpaperWin.mYOffset = offset;
230 }
231 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
232 wallpaperWin.mWallpaperY = wpy;
233 wallpaperWin.mWallpaperYStep = wpys;
234 rawChanged = true;
235 }
236
237 if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
238 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
239 try {
240 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
241 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
242 + " y=" + wallpaperWin.mWallpaperY);
243 if (sync) {
244 mWaitingOnWallpaper = wallpaperWin;
245 }
246 wallpaperWin.mClient.dispatchWallpaperOffsets(
247 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
248 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
249 if (sync) {
250 if (mWaitingOnWallpaper != null) {
251 long start = SystemClock.uptimeMillis();
252 if ((mLastWallpaperTimeoutTime + WALLPAPER_TIMEOUT_RECOVERY)
253 < start) {
254 try {
255 if (DEBUG_WALLPAPER) Slog.v(TAG,
256 "Waiting for offset complete...");
257 mService.mWindowMap.wait(WALLPAPER_TIMEOUT);
258 } catch (InterruptedException e) {
259 }
260 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
261 if ((start + WALLPAPER_TIMEOUT) < SystemClock.uptimeMillis()) {
262 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
263 + wallpaperWin);
264 mLastWallpaperTimeoutTime = start;
265 }
266 }
267 mWaitingOnWallpaper = null;
268 }
269 }
270 } catch (RemoteException e) {
271 }
272 }
273
274 return changed;
275 }
276
277 void setWindowWallpaperPosition(
278 WindowState window, float x, float y, float xStep, float yStep) {
279 if (window.mWallpaperX != x || window.mWallpaperY != y) {
280 window.mWallpaperX = x;
281 window.mWallpaperY = y;
282 window.mWallpaperXStep = xStep;
283 window.mWallpaperYStep = yStep;
284 updateWallpaperOffsetLocked(window, true);
285 }
286 }
287
288 void setWindowWallpaperDisplayOffset(WindowState window, int x, int y) {
289 if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y) {
290 window.mWallpaperDisplayOffsetX = x;
291 window.mWallpaperDisplayOffsetY = y;
292 updateWallpaperOffsetLocked(window, true);
293 }
294 }
295
296 Bundle sendWindowWallpaperCommand(
297 WindowState window, String action, int x, int y, int z, Bundle extras, boolean sync) {
298 if (window == mWallpaperTarget
299 || window == mLowerWallpaperTarget
300 || window == mUpperWallpaperTarget) {
301 boolean doWait = sync;
302 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700303 final WindowToken token = mWallpaperTokens.get(curTokenNdx);
304 token.sendWindowWallpaperCommand(action, x, y, z, extras, sync);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700305 }
306
307 if (doWait) {
308 // TODO: Need to wait for result.
309 }
310 }
311
312 return null;
313 }
314
315 void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
316 final DisplayContent displayContent = changingTarget.getDisplayContent();
317 if (displayContent == null) {
318 return;
319 }
320 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
321 final int dw = displayInfo.logicalWidth;
322 final int dh = displayInfo.logicalHeight;
323
324 WindowState target = mWallpaperTarget;
325 if (target != null) {
326 if (target.mWallpaperX >= 0) {
327 mLastWallpaperX = target.mWallpaperX;
328 } else if (changingTarget.mWallpaperX >= 0) {
329 mLastWallpaperX = changingTarget.mWallpaperX;
330 }
331 if (target.mWallpaperY >= 0) {
332 mLastWallpaperY = target.mWallpaperY;
333 } else if (changingTarget.mWallpaperY >= 0) {
334 mLastWallpaperY = changingTarget.mWallpaperY;
335 }
336 if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
337 mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
338 } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
339 mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
340 }
341 if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
342 mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
343 } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
344 mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
345 }
346 if (target.mWallpaperXStep >= 0) {
347 mLastWallpaperXStep = target.mWallpaperXStep;
348 } else if (changingTarget.mWallpaperXStep >= 0) {
349 mLastWallpaperXStep = changingTarget.mWallpaperXStep;
350 }
351 if (target.mWallpaperYStep >= 0) {
352 mLastWallpaperYStep = target.mWallpaperYStep;
353 } else if (changingTarget.mWallpaperYStep >= 0) {
354 mLastWallpaperYStep = changingTarget.mWallpaperYStep;
355 }
356 }
357
358 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700359 mWallpaperTokens.get(curTokenNdx).updateWallpaperOffset(dw, dh, sync);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700360 }
361 }
362
363 void clearLastWallpaperTimeoutTime() {
364 mLastWallpaperTimeoutTime = 0;
365 }
366
367 void wallpaperCommandComplete(IBinder window) {
368 if (mWaitingOnWallpaper != null &&
369 mWaitingOnWallpaper.mClient.asBinder() == window) {
370 mWaitingOnWallpaper = null;
371 mService.mWindowMap.notifyAll();
372 }
373 }
374
375 void wallpaperOffsetsComplete(IBinder window) {
376 if (mWaitingOnWallpaper != null &&
377 mWaitingOnWallpaper.mClient.asBinder() == window) {
378 mWaitingOnWallpaper = null;
379 mService.mWindowMap.notifyAll();
380 }
381 }
382
383 int getAnimLayerAdjustment() {
384 return mWallpaperAnimLayerAdjustment;
385 }
386
387 void setAnimLayerAdjustment(WindowState win, int adj) {
388 if (win != mWallpaperTarget || mLowerWallpaperTarget != null) {
389 return;
390 }
391
392 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Setting wallpaper layer adj to " + adj);
393 mWallpaperAnimLayerAdjustment = adj;
394 for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700395 mWallpaperTokens.get(i).adjustAnimLayer(adj);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700396 }
397 }
398
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700399 private void findWallpaperTarget(WindowList windows, FindWallpaperTargetResult result) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700400 final WindowAnimator winAnimator = mService.mAnimator;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700401 result.reset();
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700402 WindowState w = null;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700403 int windowDetachedI = -1;
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700404 boolean resetTopWallpaper = false;
405 boolean inFreeformSpace = false;
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800406 boolean replacing = false;
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700407 boolean keyguardGoingAwayWithWallpaper = false;
408
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700409 for (int i = windows.size() - 1; i >= 0; i--) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700410 w = windows.get(i);
411 if ((w.mAttrs.type == TYPE_WALLPAPER)) {
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700412 if (result.topWallpaper == null || resetTopWallpaper) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700413 result.setTopWallpaper(w, i);
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700414 resetTopWallpaper = false;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700415 }
416 continue;
417 }
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700418 resetTopWallpaper = true;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700419 if (w != winAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
420 // If this window's app token is hidden and not animating,
421 // it is of no interest to us.
422 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
423 if (DEBUG_WALLPAPER) Slog.v(TAG,
424 "Skipping hidden and not animating token: " + w);
425 continue;
426 }
427 }
428 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
429 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
430
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700431 if (!inFreeformSpace) {
432 TaskStack stack = w.getStack();
433 inFreeformSpace = stack != null && stack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
434 }
435
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700436 replacing |= w.mWillReplaceWindow;
437 keyguardGoingAwayWithWallpaper |= (w.mAppToken != null
438 && w.mWinAnimator.mKeyguardGoingAwayWithWallpaper);
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800439
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700440 final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800441 if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700442 if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: #" + i + "=" + w);
443 result.setWallpaperTarget(w, i);
Jorim Jaggi5c80c412016-04-19 20:03:47 -0700444 if (w == mWallpaperTarget && w.mWinAnimator.isAnimationSet()) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700445 // The current wallpaper target is animating, so we'll look behind it for
446 // another possible target and figure out what is going on later.
447 if (DEBUG_WALLPAPER) Slog.v(TAG,
448 "Win " + w + ": token animating, looking behind.");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700449 continue;
450 }
451 break;
452 } else if (w == winAnimator.mWindowDetachedWallpaper) {
453 windowDetachedI = i;
454 }
455 }
456
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700457 if (result.wallpaperTarget != null) {
458 return;
459 }
460
461 if (windowDetachedI >= 0) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700462 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700463 "Found animating detached wallpaper activity: #" + windowDetachedI + "=" + w);
464 result.setWallpaperTarget(w, windowDetachedI);
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700465 } else if (inFreeformSpace || (replacing && mWallpaperTarget != null)) {
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700466 // In freeform mode we set the wallpaper as its own target, so we don't need an
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800467 // additional window to make it visible. When we are replacing a window and there was
468 // wallpaper before replacement, we want to keep the window until the new windows fully
469 // appear and can determine the visibility, to avoid flickering.
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700470 result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700471
472 } else if (keyguardGoingAwayWithWallpaper) {
473 // If the app is executing an animation because the keyguard is going away (and the
474 // keyguard was showing the wallpaper) keep the wallpaper during the animation so it
475 // doesn't flicker out by having it be its own target.
476 result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700477 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700478 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700479
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700480 private boolean updateWallpaperWindowsTarget(
481 WindowList windows, FindWallpaperTargetResult result) {
482
483 boolean targetChanged = false;
484 WindowState wallpaperTarget = result.wallpaperTarget;
485 int wallpaperTargetIndex = result.wallpaperTargetIndex;
486
487 if (mWallpaperTarget != wallpaperTarget
488 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != wallpaperTarget)) {
489 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
490 "New wallpaper target: " + wallpaperTarget + " oldTarget: " + mWallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700491
492 mLowerWallpaperTarget = null;
493 mUpperWallpaperTarget = null;
494
495 WindowState oldW = mWallpaperTarget;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700496 mWallpaperTarget = wallpaperTarget;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700497 targetChanged = true;
498
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700499 // Now what is happening... if the current and new targets are animating,
500 // then we are in our super special mode!
501 if (wallpaperTarget != null && oldW != null) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700502 boolean oldAnim = oldW.isAnimatingLw();
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700503 boolean foundAnim = wallpaperTarget.isAnimatingLw();
504 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
505 "New animation: " + foundAnim + " old animation: " + oldAnim);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700506 if (foundAnim && oldAnim) {
507 int oldI = windows.indexOf(oldW);
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700508 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
509 "New i: " + wallpaperTargetIndex + " old i: " + oldI);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700510 if (oldI >= 0) {
Chong Zhangb0d26702016-08-12 16:03:29 -0700511 final boolean newTargetHidden =
512 wallpaperTarget.mAppToken != null && wallpaperTarget.mAppToken.hiddenRequested;
513 final boolean oldTargetHidden =
514 oldW.mAppToken != null && oldW.mAppToken.hiddenRequested;
515 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Animating wallpapers:"
516 + " old#" + oldI + "=" + oldW + " hidden=" + oldTargetHidden
517 + " new#" + wallpaperTargetIndex + "=" + wallpaperTarget
518 + " hidden=" + newTargetHidden);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700519
Chong Zhangec8299c2016-07-29 13:09:40 -0700520 // Set the upper and lower wallpaper targets correctly,
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700521 // and make sure that we are positioning the wallpaper below the lower.
Chong Zhangec8299c2016-07-29 13:09:40 -0700522 if (wallpaperTargetIndex > oldI) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700523 // The new target is on top of the old one.
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700524 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
525 "Found target above old target.");
526 mUpperWallpaperTarget = wallpaperTarget;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700527 mLowerWallpaperTarget = oldW;
Chong Zhangb0d26702016-08-12 16:03:29 -0700528
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700529 wallpaperTarget = oldW;
530 wallpaperTargetIndex = oldI;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700531 } else {
532 // The new target is below the old one.
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700533 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
534 "Found target below old target.");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700535 mUpperWallpaperTarget = oldW;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700536 mLowerWallpaperTarget = wallpaperTarget;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700537 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700538 if (newTargetHidden && !oldTargetHidden) {
Chong Zhangec8299c2016-07-29 13:09:40 -0700539 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
540 "Old wallpaper still the target.");
Chong Zhangb0d26702016-08-12 16:03:29 -0700541 // Use the old target if new target is hidden but old target
542 // is not. If they're both hidden, still use the new target.
Chong Zhangec8299c2016-07-29 13:09:40 -0700543 mWallpaperTarget = oldW;
Chong Zhangb0d26702016-08-12 16:03:29 -0700544 } else if (newTargetHidden == oldTargetHidden
545 && !mService.mOpeningApps.contains(wallpaperTarget.mAppToken)
546 && (mService.mOpeningApps.contains(oldW.mAppToken)
547 || mService.mClosingApps.contains(oldW.mAppToken))) {
548 // If they're both hidden (or both not hidden), prefer the one that's
549 // currently in opening or closing app list, this allows transition
550 // selection logic to better determine the wallpaper status of
551 // opening/closing apps.
552 mWallpaperTarget = oldW;
Chong Zhangec8299c2016-07-29 13:09:40 -0700553 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700554 }
555 }
556 }
557
558 } else if (mLowerWallpaperTarget != null) {
559 // Is it time to stop animating?
560 if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700561 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "No longer animating wallpaper targets!");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700562 mLowerWallpaperTarget = null;
563 mUpperWallpaperTarget = null;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700564 mWallpaperTarget = wallpaperTarget;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700565 targetChanged = true;
566 }
567 }
568
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700569 result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
570 return targetChanged;
571 }
572
573 boolean updateWallpaperWindowsTargetByLayer(
574 WindowList windows, FindWallpaperTargetResult result) {
575
576 WindowState wallpaperTarget = result.wallpaperTarget;
577 int wallpaperTargetIndex = result.wallpaperTargetIndex;
578 boolean visible = wallpaperTarget != null;
579
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700580 if (visible) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700581 // The window is visible to the compositor...but is it visible to the user?
582 // That is what the wallpaper cares about.
583 visible = isWallpaperVisible(wallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700584 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
585
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700586 // If the wallpaper target is animating, we may need to copy its layer adjustment.
587 // Only do this if we are not transferring between two wallpaper targets.
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700588 mWallpaperAnimLayerAdjustment =
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700589 (mLowerWallpaperTarget == null && wallpaperTarget.mAppToken != null)
590 ? wallpaperTarget.mAppToken.mAppAnimator.animLayerAdjustment : 0;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700591
592 final int maxLayer = (mService.mPolicy.getMaxWallpaperLayer() * TYPE_LAYER_MULTIPLIER)
593 + TYPE_LAYER_OFFSET;
594
595 // Now w is the window we are supposed to be behind... but we
596 // need to be sure to also be behind any of its attached windows,
597 // AND any starting window associated with it, AND below the
598 // maximum layer the policy allows for wallpapers.
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700599 while (wallpaperTargetIndex > 0) {
Wale Ogunwalecaa53af2016-07-17 14:50:26 -0700600 final WindowState wb = windows.get(wallpaperTargetIndex - 1);
601 final WindowState wbParentWindow = wb.getParentWindow();
602 final WindowState wallpaperParentWindow = wallpaperTarget.getParentWindow();
603 if (wb.mBaseLayer < maxLayer
604 && wbParentWindow != wallpaperTarget
605 && (wallpaperParentWindow == null || wbParentWindow != wallpaperParentWindow)
606 && (wb.mAttrs.type != TYPE_APPLICATION_STARTING
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700607 || wallpaperTarget.mToken == null
608 || wb.mToken != wallpaperTarget.mToken)) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700609 // This window is not related to the previous one in any
610 // interesting way, so stop here.
611 break;
612 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700613 wallpaperTarget = wb;
614 wallpaperTargetIndex--;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700615 }
616 } else {
617 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
618 }
619
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700620 result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
621 return visible;
622 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700623
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700624 boolean updateWallpaperWindowsPlacement(WindowList windows,
625 WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible) {
626
627 // TODO(multidisplay): Wallpapers on main screen only.
628 final DisplayInfo displayInfo = mService.getDefaultDisplayContentLocked().getDisplayInfo();
629 final int dw = displayInfo.logicalWidth;
630 final int dh = displayInfo.logicalHeight;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700631
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700632 // Start stepping backwards from here, ensuring that our wallpaper windows are correctly placed.
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700633 boolean changed = false;
634 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700635 final WindowToken token = mWallpaperTokens.get(curTokenNdx);
636 changed |= token.updateWallpaperWindowsPlacement(windows, wallpaperTarget,
637 wallpaperTargetIndex, visible, dw, dh, mWallpaperAnimLayerAdjustment);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700638 }
639
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700640 return changed;
641 }
642
643 boolean adjustWallpaperWindows() {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700644 mService.mRoot.mWallpaperMayChange = false;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700645
646 final WindowList windows = mService.getDefaultWindowListLocked();
647 // First find top-most window that has asked to be on top of the wallpaper;
648 // all wallpapers go behind it.
649 findWallpaperTarget(windows, mFindResults);
650 final boolean targetChanged = updateWallpaperWindowsTarget(windows, mFindResults);
651 final boolean visible = updateWallpaperWindowsTargetByLayer(windows, mFindResults);
652 WindowState wallpaperTarget = mFindResults.wallpaperTarget;
653 int wallpaperTargetIndex = mFindResults.wallpaperTargetIndex;
654
655 if (wallpaperTarget == null && mFindResults.topWallpaper != null) {
656 // There is no wallpaper target, so it goes at the bottom.
657 // We will assume it is the same place as last time, if known.
658 wallpaperTarget = mFindResults.topWallpaper;
659 wallpaperTargetIndex = mFindResults.topWallpaperIndex + 1;
660 } else {
661 // Okay i is the position immediately above the wallpaper.
662 // Look at what is below it for later.
663 wallpaperTarget = wallpaperTargetIndex > 0
664 ? windows.get(wallpaperTargetIndex - 1) : null;
665 }
666
667 if (visible) {
668 if (mWallpaperTarget.mWallpaperX >= 0) {
669 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
670 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
671 }
672 if (mWallpaperTarget.mWallpaperY >= 0) {
673 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
674 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
675 }
676 if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
677 mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
678 }
679 if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
680 mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
681 }
682 }
683
684 final boolean changed = updateWallpaperWindowsPlacement(
685 windows, wallpaperTarget, wallpaperTargetIndex, visible);
686
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700687 if (targetChanged && DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, "New wallpaper: target="
688 + mWallpaperTarget + " lower=" + mLowerWallpaperTarget + " upper="
689 + mUpperWallpaperTarget);
690
691 return changed;
692 }
693
694 boolean processWallpaperDrawPendingTimeout() {
695 if (mWallpaperDrawState == WALLPAPER_DRAW_PENDING) {
696 mWallpaperDrawState = WALLPAPER_DRAW_TIMEOUT;
697 if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
698 "*** WALLPAPER DRAW TIMEOUT");
699 return true;
700 }
701 return false;
702 }
703
704 boolean wallpaperTransitionReady() {
705 boolean transitionReady = true;
706 boolean wallpaperReady = true;
707 for (int curTokenIndex = mWallpaperTokens.size() - 1;
708 curTokenIndex >= 0 && wallpaperReady; curTokenIndex--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700709 final WindowToken token = mWallpaperTokens.get(curTokenIndex);
710 if (token.hasVisibleNotDrawnWallpaper()) {
711 // We've told this wallpaper to be visible, but it is not drawn yet
712 wallpaperReady = false;
713 if (mWallpaperDrawState != WALLPAPER_DRAW_TIMEOUT) {
714 // wait for this wallpaper until it is drawn or timeout
715 transitionReady = false;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700716 }
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700717 if (mWallpaperDrawState == WALLPAPER_DRAW_NORMAL) {
718 mWallpaperDrawState = WALLPAPER_DRAW_PENDING;
719 mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
720 mService.mH.sendEmptyMessageDelayed(WALLPAPER_DRAW_PENDING_TIMEOUT,
721 WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION);
722 }
723 if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
724 "Wallpaper should be visible but has not been drawn yet. " +
725 "mWallpaperDrawState=" + mWallpaperDrawState);
726 break;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700727 }
728 }
729 if (wallpaperReady) {
730 mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
731 mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
732 }
733
734 return transitionReady;
735 }
736
737 void addWallpaperToken(WindowToken token) {
738 mWallpaperTokens.add(token);
739 }
740
741 void removeWallpaperToken(WindowToken token) {
742 mWallpaperTokens.remove(token);
743 }
744
745 void dump(PrintWriter pw, String prefix) {
746 pw.print(prefix); pw.print("mWallpaperTarget="); pw.println(mWallpaperTarget);
747 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
748 pw.print(prefix); pw.print("mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
749 pw.print(prefix); pw.print("mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
750 }
751 pw.print(prefix); pw.print("mLastWallpaperX="); pw.print(mLastWallpaperX);
752 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
753 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE
754 || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
755 pw.print(prefix);
756 pw.print("mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX);
757 pw.print(" mLastWallpaperDisplayOffsetY="); pw.println(mLastWallpaperDisplayOffsetY);
758 }
759 }
760
761 void dumpTokens(PrintWriter pw, String prefix, boolean dumpAll) {
762 if (!mWallpaperTokens.isEmpty()) {
763 pw.println();
764 pw.print(prefix); pw.println("Wallpaper tokens:");
765 for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
766 WindowToken token = mWallpaperTokens.get(i);
767 pw.print(prefix); pw.print("Wallpaper #"); pw.print(i);
768 pw.print(' '); pw.print(token);
769 if (dumpAll) {
770 pw.println(':');
771 token.dump(pw, " ");
772 } else {
773 pw.println();
774 }
775 }
776 }
777 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700778
779 /** Helper class for storing the results of a wallpaper target find operation. */
780 final private static class FindWallpaperTargetResult {
781 int topWallpaperIndex = 0;
782 WindowState topWallpaper = null;
783 int wallpaperTargetIndex = 0;
784 WindowState wallpaperTarget = null;
785
786 void setTopWallpaper(WindowState win, int index) {
787 topWallpaper = win;
788 topWallpaperIndex = index;
789 }
790
791 void setWallpaperTarget(WindowState win, int index) {
792 wallpaperTarget = win;
793 wallpaperTargetIndex = index;
794 }
795
796 void reset() {
797 topWallpaperIndex = 0;
798 topWallpaper = null;
799 wallpaperTargetIndex = 0;
800 wallpaperTarget = null;
801 }
802 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700803}