blob: 0e110be1827203950449845de9ee8a328d508f89 [file] [log] [blame]
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08001/*
2 * Copyright (C) 2011 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
19import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
20
21import com.android.server.wm.WindowManagerService.H;
22
23import android.content.pm.ActivityInfo;
24import android.os.Message;
25import android.os.RemoteException;
26import android.util.Slog;
27import android.view.IApplicationToken;
28import android.view.View;
29import android.view.WindowManager;
Craig Mautnere32c3072012-03-12 15:25:35 -070030import android.view.WindowManagerPolicy;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080031import android.view.animation.Animation;
32import android.view.animation.Transformation;
33
34import java.io.PrintWriter;
35import java.util.ArrayList;
36
37/**
38 * Version of WindowToken that is specifically for a particular application (or
39 * really activity) that is displaying windows.
40 */
Craig Mautnere32c3072012-03-12 15:25:35 -070041class AppWindowToken extends WindowToken {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080042 // Non-null only for application tokens.
43 final IApplicationToken appToken;
44
45 // All of the windows and child windows that are included in this
46 // application token. Note this list is NOT sorted!
47 final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
48
49 int groupId = -1;
50 boolean appFullscreen;
51 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
52
53 // The input dispatching timeout for this application token in nanoseconds.
54 long inputDispatchingTimeoutNanos;
55
56 // These are used for determining when all windows associated with
57 // an activity have been drawn, so they can be made visible together
58 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -070059 // initialize so that it doesn't match mTransactionSequence which is an int.
60 long lastTransactionSequence = Long.MIN_VALUE;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080061 int numInterestingWindows;
62 int numDrawnWindows;
63 boolean inPendingTransaction;
64 boolean allDrawn;
65
66 // Is this token going to be hidden in a little while? If so, it
67 // won't be taken into account for setting the screen orientation.
68 boolean willBeHidden;
69
70 // Is this window's surface needed? This is almost like hidden, except
71 // it will sometimes be true a little earlier: when the token has
72 // been shown, but is still waiting for its app transition to execute
73 // before making its windows shown.
74 boolean hiddenRequested;
75
76 // Have we told the window clients to hide themselves?
77 boolean clientHidden;
78
79 // Last visibility state we reported to the app token.
80 boolean reportedVisible;
81
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -070082 // Last drawn state we reported to the app token.
83 boolean reportedDrawn;
84
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080085 // Set to true when the token has been removed from the window mgr.
86 boolean removed;
87
88 // Have we been asked to have this token keep the screen frozen?
89 boolean freezingScreen;
90
91 boolean animating;
92 Animation animation;
93 boolean hasTransformation;
94 final Transformation transformation = new Transformation();
95
96 // Offset to the window of all layers in the token, for use by
97 // AppWindowToken animations.
98 int animLayerAdjustment;
99
100 // Information about an application starting window if displayed.
101 StartingData startingData;
102 WindowState startingWindow;
103 View startingView;
104 boolean startingDisplayed;
105 boolean startingMoved;
106 boolean firstWindowDrawn;
107
108 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700109 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800110
111 AppWindowToken(WindowManagerService _service, IApplicationToken _token) {
112 super(_service, _token.asBinder(),
113 WindowManager.LayoutParams.TYPE_APPLICATION, true);
114 appWindowToken = this;
115 appToken = _token;
116 mInputApplicationHandle = new InputApplicationHandle(this);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800117 }
118
119 public void setAnimation(Animation anim) {
120 if (WindowManagerService.localLOGV) Slog.v(
121 WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
122 animation = anim;
123 animating = false;
124 anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
125 anim.scaleCurrentDuration(service.mTransitionAnimationScale);
126 int zorder = anim.getZAdjustment();
127 int adj = 0;
128 if (zorder == Animation.ZORDER_TOP) {
129 adj = WindowManagerService.TYPE_LAYER_OFFSET;
130 } else if (zorder == Animation.ZORDER_BOTTOM) {
131 adj = -WindowManagerService.TYPE_LAYER_OFFSET;
132 }
133
134 if (animLayerAdjustment != adj) {
135 animLayerAdjustment = adj;
136 updateLayers();
137 }
Craig Mautner22ce1412012-03-20 10:16:26 -0700138 // Start out animation gone if window is gone, or visible if window is visible.
139 transformation.clear();
140 transformation.setAlpha(reportedVisible ? 1 : 0);
141 hasTransformation = true;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800142 }
143
144 public void setDummyAnimation() {
145 if (animation == null) {
146 if (WindowManagerService.localLOGV) Slog.v(
147 WindowManagerService.TAG, "Setting dummy animation in " + this);
148 animation = WindowManagerService.sDummyAnimation;
149 }
150 }
151
152 public void clearAnimation() {
153 if (animation != null) {
154 animation = null;
155 animating = true;
156 }
157 }
158
159 void updateLayers() {
160 final int N = allAppWindows.size();
161 final int adj = animLayerAdjustment;
162 for (int i=0; i<N; i++) {
163 WindowState w = allAppWindows.get(i);
164 w.mAnimLayer = w.mLayer + adj;
165 if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": "
166 + w.mAnimLayer);
167 if (w == service.mInputMethodTarget && !service.mInputMethodTargetWaitingAnim) {
168 service.setInputMethodAnimLayerAdjustment(adj);
169 }
170 if (w == service.mWallpaperTarget && service.mLowerWallpaperTarget == null) {
171 service.setWallpaperAnimLayerAdjustmentLocked(adj);
172 }
173 }
174 }
175
176 void sendAppVisibilityToClients() {
177 final int N = allAppWindows.size();
178 for (int i=0; i<N; i++) {
179 WindowState win = allAppWindows.get(i);
180 if (win == startingWindow && clientHidden) {
181 // Don't hide the starting window.
182 continue;
183 }
184 try {
185 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
186 "Setting visibility of " + win + ": " + (!clientHidden));
187 win.mClient.dispatchAppVisibility(!clientHidden);
188 } catch (RemoteException e) {
189 }
190 }
191 }
192
Craig Mautner03273d02012-03-21 11:52:40 -0700193 boolean showAllWindowsLocked() {
194 boolean isAnimating = false;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800195 final int NW = allAppWindows.size();
196 for (int i=0; i<NW; i++) {
197 WindowState w = allAppWindows.get(i);
198 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
199 "performing show on: " + w);
200 w.performShowLocked();
Craig Mautner03273d02012-03-21 11:52:40 -0700201 isAnimating |= w.isAnimating();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800202 }
Craig Mautner03273d02012-03-21 11:52:40 -0700203 return isAnimating;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800204 }
205
Craig Mautnere32c3072012-03-12 15:25:35 -0700206
207 private boolean stepAnimation(long currentTime) {
Craig Mautnerdbb79912012-03-01 18:59:14 -0800208 if (animation == null) {
209 return false;
210 }
211 transformation.clear();
212 final boolean more = animation.getTransformation(currentTime, transformation);
213 if (WindowManagerService.DEBUG_ANIM) Slog.v(
214 WindowManagerService.TAG, "Stepped animation in " + this +
215 ": more=" + more + ", xform=" + transformation);
216 if (!more) {
217 animation = null;
218 if (WindowManagerService.DEBUG_ANIM) Slog.v(
219 WindowManagerService.TAG, "Finished animation in " + this +
220 " @ " + currentTime);
221 }
222 hasTransformation = more;
223 return more;
224 }
225
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800226 // This must be called while inside a transaction.
Craig Mautnere32c3072012-03-12 15:25:35 -0700227 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
Craig Mautner2fb98b12012-03-20 17:24:00 -0700228 if (service.okToDisplay()) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800229 // We will run animations as long as the display isn't frozen.
230
231 if (animation == WindowManagerService.sDummyAnimation) {
232 // This guy is going to animate, but not yet. For now count
233 // it as not animating for purposes of scheduling transactions;
234 // when it is really time to animate, this will be set to
235 // a real animation and the next call will execute normally.
236 return false;
237 }
238
239 if ((allDrawn || animating || startingDisplayed) && animation != null) {
240 if (!animating) {
241 if (WindowManagerService.DEBUG_ANIM) Slog.v(
242 WindowManagerService.TAG, "Starting animation in " + this +
243 " @ " + currentTime + ": dw=" + dw + " dh=" + dh
244 + " scale=" + service.mTransitionAnimationScale
245 + " allDrawn=" + allDrawn + " animating=" + animating);
246 animation.initialize(dw, dh, dw, dh);
247 animation.setStartTime(currentTime);
248 animating = true;
249 }
Craig Mautner1dd3ed02012-03-16 14:01:16 -0700250 if (stepAnimation(currentTime)) {
251 // we're done!
252 return true;
253 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800254 }
255 } else if (animation != null) {
256 // If the display is frozen, and there is a pending animation,
257 // clear it and make sure we run the cleanup code.
258 animating = true;
259 animation = null;
260 }
261
262 hasTransformation = false;
263
264 if (!animating) {
265 return false;
266 }
267
Craig Mautnere32c3072012-03-12 15:25:35 -0700268 service.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800269 clearAnimation();
270 animating = false;
271 if (animLayerAdjustment != 0) {
272 animLayerAdjustment = 0;
273 updateLayers();
274 }
275 if (service.mInputMethodTarget != null && service.mInputMethodTarget.mAppToken == this) {
276 service.moveInputMethodWindowsIfNeededLocked(true);
277 }
278
279 if (WindowManagerService.DEBUG_ANIM) Slog.v(
280 WindowManagerService.TAG, "Animation done in " + this
281 + ": reportedVisible=" + reportedVisible);
282
283 transformation.clear();
284
285 final int N = windows.size();
286 for (int i=0; i<N; i++) {
287 windows.get(i).finishExit();
288 }
289 updateReportedVisibilityLocked();
290
291 return false;
292 }
293
294 void updateReportedVisibilityLocked() {
295 if (appToken == null) {
296 return;
297 }
298
299 int numInteresting = 0;
300 int numVisible = 0;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700301 int numDrawn = 0;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800302 boolean nowGone = true;
303
304 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Update reported visibility: " + this);
305 final int N = allAppWindows.size();
306 for (int i=0; i<N; i++) {
307 WindowState win = allAppWindows.get(i);
308 if (win == startingWindow || win.mAppFreezing
309 || win.mViewVisibility != View.VISIBLE
310 || win.mAttrs.type == TYPE_APPLICATION_STARTING
311 || win.mDestroying) {
312 continue;
313 }
314 if (WindowManagerService.DEBUG_VISIBILITY) {
315 Slog.v(WindowManagerService.TAG, "Win " + win + ": isDrawn="
316 + win.isDrawnLw()
317 + ", isAnimating=" + win.isAnimating());
318 if (!win.isDrawnLw()) {
319 Slog.v(WindowManagerService.TAG, "Not displayed: s=" + win.mSurface
320 + " pv=" + win.mPolicyVisibility
321 + " dp=" + win.mDrawPending
322 + " cdp=" + win.mCommitDrawPending
323 + " ah=" + win.mAttachedHidden
324 + " th="
325 + (win.mAppToken != null
326 ? win.mAppToken.hiddenRequested : false)
327 + " a=" + win.mAnimating);
328 }
329 }
330 numInteresting++;
331 if (win.isDrawnLw()) {
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700332 numDrawn++;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800333 if (!win.isAnimating()) {
334 numVisible++;
335 }
336 nowGone = false;
337 } else if (win.isAnimating()) {
338 nowGone = false;
339 }
340 }
341
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700342 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800343 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700344 if (!nowGone) {
345 // If the app is not yet gone, then it can only become visible/drawn.
346 if (!nowDrawn) {
347 nowDrawn = reportedDrawn;
348 }
349 if (!nowVisible) {
350 nowVisible = reportedVisible;
351 }
352 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800353 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "VIS " + this + ": interesting="
354 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700355 if (nowDrawn != reportedDrawn) {
356 if (nowDrawn) {
357 Message m = service.mH.obtainMessage(
358 H.REPORT_APPLICATION_TOKEN_DRAWN, this);
359 service.mH.sendMessage(m);
360 }
361 reportedDrawn = nowDrawn;
362 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800363 if (nowVisible != reportedVisible) {
364 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(
365 WindowManagerService.TAG, "Visibility changed in " + this
366 + ": vis=" + nowVisible);
367 reportedVisible = nowVisible;
368 Message m = service.mH.obtainMessage(
369 H.REPORT_APPLICATION_TOKEN_WINDOWS,
370 nowVisible ? 1 : 0,
371 nowGone ? 1 : 0,
372 this);
373 service.mH.sendMessage(m);
374 }
375 }
376
377 WindowState findMainWindow() {
378 int j = windows.size();
379 while (j > 0) {
380 j--;
381 WindowState win = windows.get(j);
382 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
383 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
384 return win;
385 }
386 }
387 return null;
388 }
389
Craig Mautnerdbb79912012-03-01 18:59:14 -0800390 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800391 void dump(PrintWriter pw, String prefix) {
392 super.dump(pw, prefix);
393 if (appToken != null) {
394 pw.print(prefix); pw.println("app=true");
395 }
396 if (allAppWindows.size() > 0) {
397 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
398 }
399 pw.print(prefix); pw.print("groupId="); pw.print(groupId);
400 pw.print(" appFullscreen="); pw.print(appFullscreen);
401 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
402 pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
403 pw.print(" clientHidden="); pw.print(clientHidden);
404 pw.print(" willBeHidden="); pw.print(willBeHidden);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700405 pw.print(" reportedDrawn="); pw.print(reportedDrawn);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800406 pw.print(" reportedVisible="); pw.println(reportedVisible);
407 if (paused || freezingScreen) {
408 pw.print(prefix); pw.print("paused="); pw.print(paused);
409 pw.print(" freezingScreen="); pw.println(freezingScreen);
410 }
411 if (numInterestingWindows != 0 || numDrawnWindows != 0
412 || inPendingTransaction || allDrawn) {
413 pw.print(prefix); pw.print("numInterestingWindows=");
414 pw.print(numInterestingWindows);
415 pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
416 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
417 pw.print(" allDrawn="); pw.println(allDrawn);
418 }
419 if (animating || animation != null) {
420 pw.print(prefix); pw.print("animating="); pw.print(animating);
421 pw.print(" animation="); pw.println(animation);
422 }
423 if (hasTransformation) {
424 pw.print(prefix); pw.print("XForm: ");
425 transformation.printShortString(pw);
426 pw.println();
427 }
428 if (animLayerAdjustment != 0) {
429 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
430 }
431 if (startingData != null || removed || firstWindowDrawn) {
432 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
433 pw.print(" removed="); pw.print(removed);
434 pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
435 }
436 if (startingWindow != null || startingView != null
437 || startingDisplayed || startingMoved) {
438 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
439 pw.print(" startingView="); pw.print(startingView);
440 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
441 pw.print(" startingMoved"); pw.println(startingMoved);
442 }
443 }
444
445 @Override
446 public String toString() {
447 if (stringName == null) {
448 StringBuilder sb = new StringBuilder();
449 sb.append("AppWindowToken{");
450 sb.append(Integer.toHexString(System.identityHashCode(this)));
451 sb.append(" token="); sb.append(token); sb.append('}');
452 stringName = sb.toString();
453 }
454 return stringName;
455 }
456}