blob: 8dbf2b3e019ff16b8262da09dba85a953bac9404 [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 Ogunwalef4ebe2e2016-11-09 13:24:43 -080020import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070021import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Jorim Jaggife762342016-10-13 14:33:27 +020022import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070023import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -070024import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Jorim Jaggife762342016-10-13 14:33:27 +020025
26import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080027import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080028import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
29import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
30import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
31import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070032import static com.android.server.wm.WindowManagerService.H.WALLPAPER_DRAW_PENDING_TIMEOUT;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070033
34import android.os.Bundle;
35import android.os.Debug;
36import android.os.IBinder;
37import android.os.RemoteException;
38import android.os.SystemClock;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -070039import android.util.ArraySet;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070040import android.util.Slog;
41import android.view.DisplayInfo;
42import android.view.WindowManager;
Jorim Jaggife762342016-10-13 14:33:27 +020043import android.view.animation.Animation;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070044
45import java.io.PrintWriter;
46import java.util.ArrayList;
47
48/**
49 * Controls wallpaper windows visibility, ordering, and so on.
50 * NOTE: All methods in this class must be called with the window manager service lock held.
51 */
52class WallpaperController {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080053 private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperController" : TAG_WM;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070054 final private WindowManagerService mService;
55
Jorim Jaggi879ff722016-11-04 18:08:17 -070056 private final ArrayList<WallpaperWindowToken> mWallpaperTokens = new ArrayList<>();
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070057
58 // If non-null, this is the currently visible window that is associated
59 // with the wallpaper.
60 private WindowState mWallpaperTarget = null;
61 // If non-null, we are in the middle of animating from one wallpaper target
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -080062 // to another, and this is the previous wallpaper target.
63 private WindowState mPrevWallpaperTarget = null;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070064
65 private int mWallpaperAnimLayerAdjustment;
66
67 private float mLastWallpaperX = -1;
68 private float mLastWallpaperY = -1;
69 private float mLastWallpaperXStep = -1;
70 private float mLastWallpaperYStep = -1;
71 private int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE;
72 private int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE;
73
74 // This is set when we are waiting for a wallpaper to tell us it is done
75 // changing its scroll position.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -080076 private WindowState mWaitingOnWallpaper;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070077
78 // The last time we had a timeout when waiting for a wallpaper.
79 private long mLastWallpaperTimeoutTime;
80 // We give a wallpaper up to 150ms to finish scrolling.
81 private static final long WALLPAPER_TIMEOUT = 150;
82 // Time we wait after a timeout before trying to wait again.
83 private static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
84
85 // Set to the wallpaper window we would like to hide once the transition animations are done.
86 // This is useful in cases where we don't want the wallpaper to be hidden when the close app
87 // is a wallpaper target and is done animating out, but the opening app isn't a wallpaper
88 // target and isn't done animating in.
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070089 WindowState mDeferredHideWallpaper = null;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -070090
91 // We give a wallpaper up to 500ms to finish drawing before playing app transitions.
92 private static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 500;
93 private static final int WALLPAPER_DRAW_NORMAL = 0;
94 private static final int WALLPAPER_DRAW_PENDING = 1;
95 private static final int WALLPAPER_DRAW_TIMEOUT = 2;
96 private int mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
97
Wale Ogunwale5f61d042015-08-20 10:09:47 -070098 private final FindWallpaperTargetResult mFindResults = new FindWallpaperTargetResult();
99
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700100 public WallpaperController(WindowManagerService service) {
101 mService = service;
102 }
103
104 WindowState getWallpaperTarget() {
105 return mWallpaperTarget;
106 }
107
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700108 boolean isWallpaperTarget(WindowState win) {
109 return win == mWallpaperTarget;
110 }
111
112 boolean isBelowWallpaperTarget(WindowState win) {
113 return mWallpaperTarget != null && mWallpaperTarget.mLayer >= win.mBaseLayer;
114 }
115
116 boolean isWallpaperVisible() {
117 return isWallpaperVisible(mWallpaperTarget);
118 }
119
Jorim Jaggife762342016-10-13 14:33:27 +0200120 /**
121 * Starts {@param a} on all wallpaper windows.
122 */
123 void startWallpaperAnimation(Animation a) {
124 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Jorim Jaggi879ff722016-11-04 18:08:17 -0700125 final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
Jorim Jaggife762342016-10-13 14:33:27 +0200126 token.startAnimation(a);
127 }
128 }
129
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700130 private boolean isWallpaperVisible(WindowState wallpaperTarget) {
131 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
132 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
133 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
134 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800135 + " prev=" + mPrevWallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700136 return (wallpaperTarget != null
137 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
138 && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800139 || mPrevWallpaperTarget != null;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700140 }
141
142 boolean isWallpaperTargetAnimating() {
Jorim Jaggi5c80c412016-04-19 20:03:47 -0700143 return mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimationSet()
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700144 && !mWallpaperTarget.mWinAnimator.isDummyAnimation();
145 }
146
147 void updateWallpaperVisibility() {
Filip Gruszczynski63a35e22015-11-05 15:38:59 -0800148 final boolean visible = isWallpaperVisible(mWallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700149
150 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Jorim Jaggi879ff722016-11-04 18:08:17 -0700151 final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700152 token.updateWallpaperVisibility(visible);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700153 }
154 }
155
156 void hideDeferredWallpapersIfNeeded() {
157 if (mDeferredHideWallpaper != null) {
158 hideWallpapers(mDeferredHideWallpaper);
159 mDeferredHideWallpaper = null;
160 }
161 }
162
163 void hideWallpapers(final WindowState winGoingAway) {
164 if (mWallpaperTarget != null
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800165 && (mWallpaperTarget != winGoingAway || mPrevWallpaperTarget != null)) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700166 return;
167 }
168 if (mService.mAppTransition.isRunning()) {
169 // Defer hiding the wallpaper when app transition is running until the animations
170 // are done.
171 mDeferredHideWallpaper = winGoingAway;
172 return;
173 }
174
175 final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway);
176 for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
Jorim Jaggi879ff722016-11-04 18:08:17 -0700177 final WallpaperWindowToken token = mWallpaperTokens.get(i);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700178 token.hideWallpaperToken(wasDeferred, "hideWallpapers");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700179 if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800180 + " from " + winGoingAway + " target=" + mWallpaperTarget + " prev="
181 + mPrevWallpaperTarget + "\n" + Debug.getCallers(5, " "));
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700182 }
183 }
184
185 boolean updateWallpaperOffset(WindowState wallpaperWin, int dw, int dh, boolean sync) {
186 boolean rawChanged = false;
Winson4b4ba902016-07-27 19:45:52 -0700187 // Set the default wallpaper x-offset to either edge of the screen (depending on RTL), to
188 // match the behavior of most Launchers
189 float defaultWallpaperX = wallpaperWin.isRtl() ? 1f : 0f;
190 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : defaultWallpaperX;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700191 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
192 int availw = wallpaperWin.mFrame.right - wallpaperWin.mFrame.left - dw;
193 int offset = availw > 0 ? -(int)(availw * wpx + .5f) : 0;
194 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
195 offset += mLastWallpaperDisplayOffsetX;
196 }
197 boolean changed = wallpaperWin.mXOffset != offset;
198 if (changed) {
199 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " x: " + offset);
200 wallpaperWin.mXOffset = offset;
201 }
202 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
203 wallpaperWin.mWallpaperX = wpx;
204 wallpaperWin.mWallpaperXStep = wpxs;
205 rawChanged = true;
206 }
207
208 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
209 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
210 int availh = wallpaperWin.mFrame.bottom - wallpaperWin.mFrame.top - dh;
211 offset = availh > 0 ? -(int)(availh * wpy + .5f) : 0;
212 if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
213 offset += mLastWallpaperDisplayOffsetY;
214 }
215 if (wallpaperWin.mYOffset != offset) {
216 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " y: " + offset);
217 changed = true;
218 wallpaperWin.mYOffset = offset;
219 }
220 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
221 wallpaperWin.mWallpaperY = wpy;
222 wallpaperWin.mWallpaperYStep = wpys;
223 rawChanged = true;
224 }
225
226 if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
227 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
228 try {
229 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
230 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
231 + " y=" + wallpaperWin.mWallpaperY);
232 if (sync) {
233 mWaitingOnWallpaper = wallpaperWin;
234 }
235 wallpaperWin.mClient.dispatchWallpaperOffsets(
236 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
237 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
238 if (sync) {
239 if (mWaitingOnWallpaper != null) {
240 long start = SystemClock.uptimeMillis();
241 if ((mLastWallpaperTimeoutTime + WALLPAPER_TIMEOUT_RECOVERY)
242 < start) {
243 try {
244 if (DEBUG_WALLPAPER) Slog.v(TAG,
245 "Waiting for offset complete...");
246 mService.mWindowMap.wait(WALLPAPER_TIMEOUT);
247 } catch (InterruptedException e) {
248 }
249 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
250 if ((start + WALLPAPER_TIMEOUT) < SystemClock.uptimeMillis()) {
251 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
252 + wallpaperWin);
253 mLastWallpaperTimeoutTime = start;
254 }
255 }
256 mWaitingOnWallpaper = null;
257 }
258 }
259 } catch (RemoteException e) {
260 }
261 }
262
263 return changed;
264 }
265
266 void setWindowWallpaperPosition(
267 WindowState window, float x, float y, float xStep, float yStep) {
268 if (window.mWallpaperX != x || window.mWallpaperY != y) {
269 window.mWallpaperX = x;
270 window.mWallpaperY = y;
271 window.mWallpaperXStep = xStep;
272 window.mWallpaperYStep = yStep;
273 updateWallpaperOffsetLocked(window, true);
274 }
275 }
276
277 void setWindowWallpaperDisplayOffset(WindowState window, int x, int y) {
278 if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y) {
279 window.mWallpaperDisplayOffsetX = x;
280 window.mWallpaperDisplayOffsetY = y;
281 updateWallpaperOffsetLocked(window, true);
282 }
283 }
284
285 Bundle sendWindowWallpaperCommand(
286 WindowState window, String action, int x, int y, int z, Bundle extras, boolean sync) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800287 if (window == mWallpaperTarget || window == mPrevWallpaperTarget) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700288 boolean doWait = sync;
289 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Jorim Jaggi879ff722016-11-04 18:08:17 -0700290 final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700291 token.sendWindowWallpaperCommand(action, x, y, z, extras, sync);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700292 }
293
294 if (doWait) {
295 // TODO: Need to wait for result.
296 }
297 }
298
299 return null;
300 }
301
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700302 private void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700303 final DisplayContent displayContent = changingTarget.getDisplayContent();
304 if (displayContent == null) {
305 return;
306 }
307 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
308 final int dw = displayInfo.logicalWidth;
309 final int dh = displayInfo.logicalHeight;
310
311 WindowState target = mWallpaperTarget;
312 if (target != null) {
313 if (target.mWallpaperX >= 0) {
314 mLastWallpaperX = target.mWallpaperX;
315 } else if (changingTarget.mWallpaperX >= 0) {
316 mLastWallpaperX = changingTarget.mWallpaperX;
317 }
318 if (target.mWallpaperY >= 0) {
319 mLastWallpaperY = target.mWallpaperY;
320 } else if (changingTarget.mWallpaperY >= 0) {
321 mLastWallpaperY = changingTarget.mWallpaperY;
322 }
323 if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
324 mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
325 } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
326 mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
327 }
328 if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
329 mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
330 } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
331 mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
332 }
333 if (target.mWallpaperXStep >= 0) {
334 mLastWallpaperXStep = target.mWallpaperXStep;
335 } else if (changingTarget.mWallpaperXStep >= 0) {
336 mLastWallpaperXStep = changingTarget.mWallpaperXStep;
337 }
338 if (target.mWallpaperYStep >= 0) {
339 mLastWallpaperYStep = target.mWallpaperYStep;
340 } else if (changingTarget.mWallpaperYStep >= 0) {
341 mLastWallpaperYStep = changingTarget.mWallpaperYStep;
342 }
343 }
344
345 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700346 mWallpaperTokens.get(curTokenNdx).updateWallpaperOffset(dw, dh, sync);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700347 }
348 }
349
350 void clearLastWallpaperTimeoutTime() {
351 mLastWallpaperTimeoutTime = 0;
352 }
353
354 void wallpaperCommandComplete(IBinder window) {
355 if (mWaitingOnWallpaper != null &&
356 mWaitingOnWallpaper.mClient.asBinder() == window) {
357 mWaitingOnWallpaper = null;
358 mService.mWindowMap.notifyAll();
359 }
360 }
361
362 void wallpaperOffsetsComplete(IBinder window) {
363 if (mWaitingOnWallpaper != null &&
364 mWaitingOnWallpaper.mClient.asBinder() == window) {
365 mWaitingOnWallpaper = null;
366 mService.mWindowMap.notifyAll();
367 }
368 }
369
370 int getAnimLayerAdjustment() {
371 return mWallpaperAnimLayerAdjustment;
372 }
373
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800374 private void findWallpaperTarget(DisplayContent dc , FindWallpaperTargetResult result) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700375 final WindowAnimator winAnimator = mService.mAnimator;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700376 result.reset();
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800377 if (mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
378 // In freeform mode we set the wallpaper as its own target, so we don't need an
379 // additional window to make it visible.
380 result.setUseTopWallpaperAsTarget(true);
381 }
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700382
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800383 dc.forAllWindows(w -> {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700384 if ((w.mAttrs.type == TYPE_WALLPAPER)) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800385 if (result.topWallpaper == null || result.resetTopWallpaper) {
386 result.setTopWallpaper(w);
387 result.resetTopWallpaper = false;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700388 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800389 return false;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700390 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800391
392 result.resetTopWallpaper = true;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700393 if (w != winAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
394 // If this window's app token is hidden and not animating,
395 // it is of no interest to us.
396 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
397 if (DEBUG_WALLPAPER) Slog.v(TAG,
398 "Skipping hidden and not animating token: " + w);
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800399 return false;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700400 }
401 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800402 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": isOnScreen=" + w.isOnScreen()
403 + " mDrawState=" + w.mWinAnimator.mDrawState);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700404
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800405 if (w.mWillReplaceWindow && mWallpaperTarget == null
406 && !result.useTopWallpaperAsTarget) {
407 // When we are replacing a window and there was wallpaper before replacement, we
408 // want to keep the window until the new windows fully appear and can determine the
409 // visibility, to avoid flickering.
410 result.setUseTopWallpaperAsTarget(true);
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700411 }
412
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800413 final boolean keyguardGoingAwayWithWallpaper = (w.mAppToken != null
Jorim Jaggife762342016-10-13 14:33:27 +0200414 && AppTransition.isKeyguardGoingAwayTransit(
415 w.mAppToken.mAppAnimator.getTransit())
416 && (w.mAppToken.mAppAnimator.getTransitFlags()
417 & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
418
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800419 boolean needsShowWhenLockedWallpaper = false;
Jorim Jaggife762342016-10-13 14:33:27 +0200420 if ((w.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
421 && mService.mPolicy.isKeyguardLocked()
422 && mService.mPolicy.isKeyguardOccluded()) {
423 // The lowest show when locked window decides whether we need to put the wallpaper
424 // behind.
425 needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
426 || (w.mAppToken != null && !w.mAppToken.fillsParent());
427 }
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800428
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800429 if (keyguardGoingAwayWithWallpaper || needsShowWhenLockedWallpaper) {
430 // Keep the wallpaper during Keyguard exit but also when it's needed for a
431 // non-fullscreen show when locked activity.
432 result.setUseTopWallpaperAsTarget(true);
433 }
434
Wale Ogunwale6cbba702016-06-28 16:27:31 -0700435 final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
Filip Gruszczynski51cb83e2015-11-05 09:32:19 -0800436 if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800437 if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: " + w);
438 result.setWallpaperTarget(w);
Jorim Jaggi5c80c412016-04-19 20:03:47 -0700439 if (w == mWallpaperTarget && w.mWinAnimator.isAnimationSet()) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700440 // The current wallpaper target is animating, so we'll look behind it for
441 // another possible target and figure out what is going on later.
442 if (DEBUG_WALLPAPER) Slog.v(TAG,
443 "Win " + w + ": token animating, looking behind.");
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700444 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800445 // Found a target! End search.
446 return true;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700447 } else if (w == winAnimator.mWindowDetachedWallpaper) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800448 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
449 "Found animating detached wallpaper target win: " + w);
450 result.setUseTopWallpaperAsTarget(true);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700451 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800452 return false;
453 }, true /* traverseTopToBottom */);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700454
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800455 if (result.wallpaperTarget == null && result.useTopWallpaperAsTarget) {
456 result.setWallpaperTarget(result.topWallpaper);
Wale Ogunwale21fdd912015-08-20 12:34:57 -0700457 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700458 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700459
Jorim Jaggife762342016-10-13 14:33:27 +0200460 private boolean isFullscreen(WindowManager.LayoutParams attrs) {
461 return attrs.x == 0 && attrs.y == 0
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800462 && attrs.width == MATCH_PARENT && attrs.height == MATCH_PARENT;
Jorim Jaggife762342016-10-13 14:33:27 +0200463 }
464
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700465 /** Updates the target wallpaper if needed and returns true if an update happened. */
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800466 private void updateWallpaperWindowsTarget(DisplayContent dc,
467 FindWallpaperTargetResult result) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700468
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700469 WindowState wallpaperTarget = result.wallpaperTarget;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700470
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700471 if (mWallpaperTarget == wallpaperTarget
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800472 || (mPrevWallpaperTarget != null && mPrevWallpaperTarget == wallpaperTarget)) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700473
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800474 if (mPrevWallpaperTarget == null) {
475 return;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700476 }
477
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800478 // Is it time to stop animating?
479 if (!mPrevWallpaperTarget.isAnimatingLw()) {
480 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "No longer animating wallpaper targets!");
481 mPrevWallpaperTarget = null;
482 mWallpaperTarget = wallpaperTarget;
483 }
484 return;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700485 }
486
487 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800488 "New wallpaper target: " + wallpaperTarget + " prevTarget: " + mWallpaperTarget);
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700489
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800490 mPrevWallpaperTarget = null;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700491
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800492 final WindowState prevWallpaperTarget = mWallpaperTarget;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700493 mWallpaperTarget = wallpaperTarget;
494
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800495 if (wallpaperTarget == null || prevWallpaperTarget == null) {
496 return;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700497 }
498
499 // Now what is happening... if the current and new targets are animating,
500 // then we are in our super special mode!
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800501 boolean oldAnim = prevWallpaperTarget.isAnimatingLw();
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700502 boolean foundAnim = wallpaperTarget.isAnimatingLw();
503 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
504 "New animation: " + foundAnim + " old animation: " + oldAnim);
505
506 if (!foundAnim || !oldAnim) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800507 return;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700508 }
509
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800510 if (dc.getWindow(w -> w == prevWallpaperTarget) == null) {
511 return;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700512 }
513
514 final boolean newTargetHidden = wallpaperTarget.mAppToken != null
515 && wallpaperTarget.mAppToken.hiddenRequested;
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800516 final boolean oldTargetHidden = prevWallpaperTarget.mAppToken != null
517 && prevWallpaperTarget.mAppToken.hiddenRequested;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700518
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800519 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Animating wallpapers:" + " old: "
520 + prevWallpaperTarget + " hidden=" + oldTargetHidden + " new: " + wallpaperTarget
521 + " hidden=" + newTargetHidden);
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700522
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800523 mPrevWallpaperTarget = prevWallpaperTarget;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700524
525 if (newTargetHidden && !oldTargetHidden) {
526 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Old wallpaper still the target.");
527 // Use the old target if new target is hidden but old target
528 // is not. If they're both hidden, still use the new target.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800529 mWallpaperTarget = prevWallpaperTarget;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700530 } else if (newTargetHidden == oldTargetHidden
531 && !mService.mOpeningApps.contains(wallpaperTarget.mAppToken)
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800532 && (mService.mOpeningApps.contains(prevWallpaperTarget.mAppToken)
533 || mService.mClosingApps.contains(prevWallpaperTarget.mAppToken))) {
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700534 // If they're both hidden (or both not hidden), prefer the one that's currently in
535 // opening or closing app list, this allows transition selection logic to better
536 // determine the wallpaper status of opening/closing apps.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800537 mWallpaperTarget = prevWallpaperTarget;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700538 }
539
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800540 result.setWallpaperTarget(wallpaperTarget);
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700541 }
542
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800543 private void updateWallpaperTokens(boolean visible) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700544 for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
Jorim Jaggi879ff722016-11-04 18:08:17 -0700545 final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800546 token.updateWallpaperWindows(visible, mWallpaperAnimLayerAdjustment);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700547 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700548 }
549
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800550 void adjustWallpaperWindows(DisplayContent dc) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700551 mService.mRoot.mWallpaperMayChange = false;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700552
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700553 // First find top-most window that has asked to be on top of the wallpaper;
554 // all wallpapers go behind it.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800555 findWallpaperTarget(dc, mFindResults);
556 updateWallpaperWindowsTarget(dc, mFindResults);
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700557
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800558 // The window is visible to the compositor...but is it visible to the user?
559 // That is what the wallpaper cares about.
560 final boolean visible = mWallpaperTarget != null && isWallpaperVisible(mWallpaperTarget);
561 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700562
563 if (visible) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800564 // If the wallpaper target is animating, we may need to copy its layer adjustment.
565 // Only do this if we are not transferring between two wallpaper targets.
566 mWallpaperAnimLayerAdjustment =
567 (mPrevWallpaperTarget == null && mWallpaperTarget.mAppToken != null)
568 ? mWallpaperTarget.mAppToken.mAppAnimator.animLayerAdjustment : 0;
569
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700570 if (mWallpaperTarget.mWallpaperX >= 0) {
571 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
572 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
573 }
574 if (mWallpaperTarget.mWallpaperY >= 0) {
575 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
576 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
577 }
578 if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
579 mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
580 }
581 if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
582 mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
583 }
584 }
585
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800586 updateWallpaperTokens(visible);
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700587
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800588 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget
589 + " prev=" + mPrevWallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700590 }
591
592 boolean processWallpaperDrawPendingTimeout() {
593 if (mWallpaperDrawState == WALLPAPER_DRAW_PENDING) {
594 mWallpaperDrawState = WALLPAPER_DRAW_TIMEOUT;
595 if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
596 "*** WALLPAPER DRAW TIMEOUT");
597 return true;
598 }
599 return false;
600 }
601
602 boolean wallpaperTransitionReady() {
603 boolean transitionReady = true;
604 boolean wallpaperReady = true;
605 for (int curTokenIndex = mWallpaperTokens.size() - 1;
606 curTokenIndex >= 0 && wallpaperReady; curTokenIndex--) {
Jorim Jaggi879ff722016-11-04 18:08:17 -0700607 final WallpaperWindowToken token = mWallpaperTokens.get(curTokenIndex);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700608 if (token.hasVisibleNotDrawnWallpaper()) {
609 // We've told this wallpaper to be visible, but it is not drawn yet
610 wallpaperReady = false;
611 if (mWallpaperDrawState != WALLPAPER_DRAW_TIMEOUT) {
612 // wait for this wallpaper until it is drawn or timeout
613 transitionReady = false;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700614 }
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700615 if (mWallpaperDrawState == WALLPAPER_DRAW_NORMAL) {
616 mWallpaperDrawState = WALLPAPER_DRAW_PENDING;
617 mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
618 mService.mH.sendEmptyMessageDelayed(WALLPAPER_DRAW_PENDING_TIMEOUT,
619 WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION);
620 }
621 if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
622 "Wallpaper should be visible but has not been drawn yet. " +
623 "mWallpaperDrawState=" + mWallpaperDrawState);
624 break;
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700625 }
626 }
627 if (wallpaperReady) {
628 mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
629 mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
630 }
631
632 return transitionReady;
633 }
634
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700635 /**
636 * Adjusts the wallpaper windows if the input display has a pending wallpaper layout or one of
637 * the opening apps should be a wallpaper target.
638 */
Wale Ogunwale0303c572016-10-20 10:16:29 -0700639 void adjustWallpaperWindowsForAppTransitionIfNeeded(DisplayContent dc,
640 ArraySet<AppWindowToken> openingApps) {
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700641 boolean adjust = false;
642 if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
643 adjust = true;
644 } else {
645 for (int i = openingApps.size() - 1; i >= 0; --i) {
646 final AppWindowToken token = openingApps.valueAt(i);
647 if (token.windowsCanBeWallpaperTarget()) {
648 adjust = true;
649 break;
650 }
651 }
652 }
653
Wale Ogunwale0303c572016-10-20 10:16:29 -0700654 if (adjust) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800655 adjustWallpaperWindows(dc);
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700656 }
657 }
658
Jorim Jaggi879ff722016-11-04 18:08:17 -0700659 void addWallpaperToken(WallpaperWindowToken token) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700660 mWallpaperTokens.add(token);
661 }
662
Jorim Jaggi879ff722016-11-04 18:08:17 -0700663 void removeWallpaperToken(WallpaperWindowToken token) {
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700664 mWallpaperTokens.remove(token);
665 }
666
667 void dump(PrintWriter pw, String prefix) {
668 pw.print(prefix); pw.print("mWallpaperTarget="); pw.println(mWallpaperTarget);
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800669 if (mPrevWallpaperTarget != null) {
670 pw.print(prefix); pw.print("mPrevWallpaperTarget="); pw.println(mPrevWallpaperTarget);
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700671 }
672 pw.print(prefix); pw.print("mLastWallpaperX="); pw.print(mLastWallpaperX);
673 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
674 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE
675 || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
676 pw.print(prefix);
677 pw.print("mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX);
678 pw.print(" mLastWallpaperDisplayOffsetY="); pw.println(mLastWallpaperDisplayOffsetY);
679 }
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700680
681 if (mWallpaperAnimLayerAdjustment != 0) {
682 pw.println(prefix + "mWallpaperAnimLayerAdjustment=" + mWallpaperAnimLayerAdjustment);
683 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700684 }
685
686 void dumpTokens(PrintWriter pw, String prefix, boolean dumpAll) {
687 if (!mWallpaperTokens.isEmpty()) {
688 pw.println();
689 pw.print(prefix); pw.println("Wallpaper tokens:");
690 for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
691 WindowToken token = mWallpaperTokens.get(i);
692 pw.print(prefix); pw.print("Wallpaper #"); pw.print(i);
693 pw.print(' '); pw.print(token);
694 if (dumpAll) {
695 pw.println(':');
696 token.dump(pw, " ");
697 } else {
698 pw.println();
699 }
700 }
701 }
702 }
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700703
704 /** Helper class for storing the results of a wallpaper target find operation. */
705 final private static class FindWallpaperTargetResult {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700706 WindowState topWallpaper = null;
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800707 boolean useTopWallpaperAsTarget = false;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700708 WindowState wallpaperTarget = null;
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800709 boolean resetTopWallpaper = false;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700710
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800711 void setTopWallpaper(WindowState win) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700712 topWallpaper = win;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700713 }
714
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800715 void setWallpaperTarget(WindowState win) {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700716 wallpaperTarget = win;
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800717 }
718
719 void setUseTopWallpaperAsTarget(boolean topWallpaperAsTarget) {
720 useTopWallpaperAsTarget = topWallpaperAsTarget;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700721 }
722
723 void reset() {
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700724 topWallpaper = null;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700725 wallpaperTarget = null;
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800726 useTopWallpaperAsTarget = false;
727 resetTopWallpaper = false;
Wale Ogunwale5f61d042015-08-20 10:09:47 -0700728 }
729 }
Wale Ogunwalee8069dc2015-08-18 09:52:01 -0700730}