• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.server.wm;
18 
19 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
20 
21 import com.android.server.wm.WindowManagerService.H;
22 
23 import android.content.pm.ActivityInfo;
24 import android.os.Message;
25 import android.os.RemoteException;
26 import android.util.Slog;
27 import android.view.IApplicationToken;
28 import android.view.View;
29 import android.view.WindowManager;
30 import android.view.animation.Animation;
31 import android.view.animation.Transformation;
32 
33 import java.io.PrintWriter;
34 import java.util.ArrayList;
35 
36 /**
37  * Version of WindowToken that is specifically for a particular application (or
38  * really activity) that is displaying windows.
39  */
40 class AppWindowToken extends WindowToken {
41     // Non-null only for application tokens.
42     final IApplicationToken appToken;
43 
44     // All of the windows and child windows that are included in this
45     // application token.  Note this list is NOT sorted!
46     final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
47 
48     int groupId = -1;
49     boolean appFullscreen;
50     int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
51 
52     // The input dispatching timeout for this application token in nanoseconds.
53     long inputDispatchingTimeoutNanos;
54 
55     // These are used for determining when all windows associated with
56     // an activity have been drawn, so they can be made visible together
57     // at the same time.
58     int lastTransactionSequence;
59     int numInterestingWindows;
60     int numDrawnWindows;
61     boolean inPendingTransaction;
62     boolean allDrawn;
63 
64     // Is this token going to be hidden in a little while?  If so, it
65     // won't be taken into account for setting the screen orientation.
66     boolean willBeHidden;
67 
68     // Is this window's surface needed?  This is almost like hidden, except
69     // it will sometimes be true a little earlier: when the token has
70     // been shown, but is still waiting for its app transition to execute
71     // before making its windows shown.
72     boolean hiddenRequested;
73 
74     // Have we told the window clients to hide themselves?
75     boolean clientHidden;
76 
77     // Last visibility state we reported to the app token.
78     boolean reportedVisible;
79 
80     // Set to true when the token has been removed from the window mgr.
81     boolean removed;
82 
83     // Have we been asked to have this token keep the screen frozen?
84     boolean freezingScreen;
85 
86     boolean animating;
87     Animation animation;
88     boolean hasTransformation;
89     final Transformation transformation = new Transformation();
90 
91     // Offset to the window of all layers in the token, for use by
92     // AppWindowToken animations.
93     int animLayerAdjustment;
94 
95     // Information about an application starting window if displayed.
96     StartingData startingData;
97     WindowState startingWindow;
98     View startingView;
99     boolean startingDisplayed;
100     boolean startingMoved;
101     boolean firstWindowDrawn;
102 
103     // Input application handle used by the input dispatcher.
104     final InputApplicationHandle mInputApplicationHandle;
105 
AppWindowToken(WindowManagerService _service, IApplicationToken _token)106     AppWindowToken(WindowManagerService _service, IApplicationToken _token) {
107         super(_service, _token.asBinder(),
108                 WindowManager.LayoutParams.TYPE_APPLICATION, true);
109         appWindowToken = this;
110         appToken = _token;
111         mInputApplicationHandle = new InputApplicationHandle(this);
112         lastTransactionSequence = service.mTransactionSequence-1;
113     }
114 
setAnimation(Animation anim)115     public void setAnimation(Animation anim) {
116         if (WindowManagerService.localLOGV) Slog.v(
117             WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
118         animation = anim;
119         animating = false;
120         anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
121         anim.scaleCurrentDuration(service.mTransitionAnimationScale);
122         int zorder = anim.getZAdjustment();
123         int adj = 0;
124         if (zorder == Animation.ZORDER_TOP) {
125             adj = WindowManagerService.TYPE_LAYER_OFFSET;
126         } else if (zorder == Animation.ZORDER_BOTTOM) {
127             adj = -WindowManagerService.TYPE_LAYER_OFFSET;
128         }
129 
130         if (animLayerAdjustment != adj) {
131             animLayerAdjustment = adj;
132             updateLayers();
133         }
134     }
135 
setDummyAnimation()136     public void setDummyAnimation() {
137         if (animation == null) {
138             if (WindowManagerService.localLOGV) Slog.v(
139                 WindowManagerService.TAG, "Setting dummy animation in " + this);
140             animation = WindowManagerService.sDummyAnimation;
141         }
142     }
143 
clearAnimation()144     public void clearAnimation() {
145         if (animation != null) {
146             animation = null;
147             animating = true;
148         }
149     }
150 
updateLayers()151     void updateLayers() {
152         final int N = allAppWindows.size();
153         final int adj = animLayerAdjustment;
154         for (int i=0; i<N; i++) {
155             WindowState w = allAppWindows.get(i);
156             w.mAnimLayer = w.mLayer + adj;
157             if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": "
158                     + w.mAnimLayer);
159             if (w == service.mInputMethodTarget && !service.mInputMethodTargetWaitingAnim) {
160                 service.setInputMethodAnimLayerAdjustment(adj);
161             }
162             if (w == service.mWallpaperTarget && service.mLowerWallpaperTarget == null) {
163                 service.setWallpaperAnimLayerAdjustmentLocked(adj);
164             }
165         }
166     }
167 
sendAppVisibilityToClients()168     void sendAppVisibilityToClients() {
169         final int N = allAppWindows.size();
170         for (int i=0; i<N; i++) {
171             WindowState win = allAppWindows.get(i);
172             if (win == startingWindow && clientHidden) {
173                 // Don't hide the starting window.
174                 continue;
175             }
176             try {
177                 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
178                         "Setting visibility of " + win + ": " + (!clientHidden));
179                 win.mClient.dispatchAppVisibility(!clientHidden);
180             } catch (RemoteException e) {
181             }
182         }
183     }
184 
showAllWindowsLocked()185     void showAllWindowsLocked() {
186         final int NW = allAppWindows.size();
187         for (int i=0; i<NW; i++) {
188             WindowState w = allAppWindows.get(i);
189             if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
190                     "performing show on: " + w);
191             w.performShowLocked();
192         }
193     }
194 
195     // This must be called while inside a transaction.
stepAnimationLocked(long currentTime, int dw, int dh)196     boolean stepAnimationLocked(long currentTime, int dw, int dh) {
197         if (!service.mDisplayFrozen && service.mPolicy.isScreenOnFully()) {
198             // We will run animations as long as the display isn't frozen.
199 
200             if (animation == WindowManagerService.sDummyAnimation) {
201                 // This guy is going to animate, but not yet.  For now count
202                 // it as not animating for purposes of scheduling transactions;
203                 // when it is really time to animate, this will be set to
204                 // a real animation and the next call will execute normally.
205                 return false;
206             }
207 
208             if ((allDrawn || animating || startingDisplayed) && animation != null) {
209                 if (!animating) {
210                     if (WindowManagerService.DEBUG_ANIM) Slog.v(
211                         WindowManagerService.TAG, "Starting animation in " + this +
212                         " @ " + currentTime + ": dw=" + dw + " dh=" + dh
213                         + " scale=" + service.mTransitionAnimationScale
214                         + " allDrawn=" + allDrawn + " animating=" + animating);
215                     animation.initialize(dw, dh, dw, dh);
216                     animation.setStartTime(currentTime);
217                     animating = true;
218                 }
219                 transformation.clear();
220                 final boolean more = animation.getTransformation(
221                     currentTime, transformation);
222                 if (WindowManagerService.DEBUG_ANIM) Slog.v(
223                     WindowManagerService.TAG, "Stepped animation in " + this +
224                     ": more=" + more + ", xform=" + transformation);
225                 if (more) {
226                     // we're done!
227                     hasTransformation = true;
228                     return true;
229                 }
230                 if (WindowManagerService.DEBUG_ANIM) Slog.v(
231                     WindowManagerService.TAG, "Finished animation in " + this +
232                     " @ " + currentTime);
233                 animation = null;
234             }
235         } else if (animation != null) {
236             // If the display is frozen, and there is a pending animation,
237             // clear it and make sure we run the cleanup code.
238             animating = true;
239             animation = null;
240         }
241 
242         hasTransformation = false;
243 
244         if (!animating) {
245             return false;
246         }
247 
248         clearAnimation();
249         animating = false;
250         if (animLayerAdjustment != 0) {
251             animLayerAdjustment = 0;
252             updateLayers();
253         }
254         if (service.mInputMethodTarget != null && service.mInputMethodTarget.mAppToken == this) {
255             service.moveInputMethodWindowsIfNeededLocked(true);
256         }
257 
258         if (WindowManagerService.DEBUG_ANIM) Slog.v(
259                 WindowManagerService.TAG, "Animation done in " + this
260                 + ": reportedVisible=" + reportedVisible);
261 
262         transformation.clear();
263 
264         final int N = windows.size();
265         for (int i=0; i<N; i++) {
266             windows.get(i).finishExit();
267         }
268         updateReportedVisibilityLocked();
269 
270         return false;
271     }
272 
updateReportedVisibilityLocked()273     void updateReportedVisibilityLocked() {
274         if (appToken == null) {
275             return;
276         }
277 
278         int numInteresting = 0;
279         int numVisible = 0;
280         boolean nowGone = true;
281 
282         if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Update reported visibility: " + this);
283         final int N = allAppWindows.size();
284         for (int i=0; i<N; i++) {
285             WindowState win = allAppWindows.get(i);
286             if (win == startingWindow || win.mAppFreezing
287                     || win.mViewVisibility != View.VISIBLE
288                     || win.mAttrs.type == TYPE_APPLICATION_STARTING
289                     || win.mDestroying) {
290                 continue;
291             }
292             if (WindowManagerService.DEBUG_VISIBILITY) {
293                 Slog.v(WindowManagerService.TAG, "Win " + win + ": isDrawn="
294                         + win.isDrawnLw()
295                         + ", isAnimating=" + win.isAnimating());
296                 if (!win.isDrawnLw()) {
297                     Slog.v(WindowManagerService.TAG, "Not displayed: s=" + win.mSurface
298                             + " pv=" + win.mPolicyVisibility
299                             + " dp=" + win.mDrawPending
300                             + " cdp=" + win.mCommitDrawPending
301                             + " ah=" + win.mAttachedHidden
302                             + " th="
303                             + (win.mAppToken != null
304                                     ? win.mAppToken.hiddenRequested : false)
305                             + " a=" + win.mAnimating);
306                 }
307             }
308             numInteresting++;
309             if (win.isDrawnLw()) {
310                 if (!win.isAnimating()) {
311                     numVisible++;
312                 }
313                 nowGone = false;
314             } else if (win.isAnimating()) {
315                 nowGone = false;
316             }
317         }
318 
319         boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
320         if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "VIS " + this + ": interesting="
321                 + numInteresting + " visible=" + numVisible);
322         if (nowVisible != reportedVisible) {
323             if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(
324                     WindowManagerService.TAG, "Visibility changed in " + this
325                     + ": vis=" + nowVisible);
326             reportedVisible = nowVisible;
327             Message m = service.mH.obtainMessage(
328                     H.REPORT_APPLICATION_TOKEN_WINDOWS,
329                     nowVisible ? 1 : 0,
330                     nowGone ? 1 : 0,
331                     this);
332             service.mH.sendMessage(m);
333         }
334     }
335 
findMainWindow()336     WindowState findMainWindow() {
337         int j = windows.size();
338         while (j > 0) {
339             j--;
340             WindowState win = windows.get(j);
341             if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
342                     || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
343                 return win;
344             }
345         }
346         return null;
347     }
348 
dump(PrintWriter pw, String prefix)349     void dump(PrintWriter pw, String prefix) {
350         super.dump(pw, prefix);
351         if (appToken != null) {
352             pw.print(prefix); pw.println("app=true");
353         }
354         if (allAppWindows.size() > 0) {
355             pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
356         }
357         pw.print(prefix); pw.print("groupId="); pw.print(groupId);
358                 pw.print(" appFullscreen="); pw.print(appFullscreen);
359                 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
360         pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
361                 pw.print(" clientHidden="); pw.print(clientHidden);
362                 pw.print(" willBeHidden="); pw.print(willBeHidden);
363                 pw.print(" reportedVisible="); pw.println(reportedVisible);
364         if (paused || freezingScreen) {
365             pw.print(prefix); pw.print("paused="); pw.print(paused);
366                     pw.print(" freezingScreen="); pw.println(freezingScreen);
367         }
368         if (numInterestingWindows != 0 || numDrawnWindows != 0
369                 || inPendingTransaction || allDrawn) {
370             pw.print(prefix); pw.print("numInterestingWindows=");
371                     pw.print(numInterestingWindows);
372                     pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
373                     pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
374                     pw.print(" allDrawn="); pw.println(allDrawn);
375         }
376         if (animating || animation != null) {
377             pw.print(prefix); pw.print("animating="); pw.print(animating);
378                     pw.print(" animation="); pw.println(animation);
379         }
380         if (hasTransformation) {
381             pw.print(prefix); pw.print("XForm: ");
382                     transformation.printShortString(pw);
383                     pw.println();
384         }
385         if (animLayerAdjustment != 0) {
386             pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
387         }
388         if (startingData != null || removed || firstWindowDrawn) {
389             pw.print(prefix); pw.print("startingData="); pw.print(startingData);
390                     pw.print(" removed="); pw.print(removed);
391                     pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
392         }
393         if (startingWindow != null || startingView != null
394                 || startingDisplayed || startingMoved) {
395             pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
396                     pw.print(" startingView="); pw.print(startingView);
397                     pw.print(" startingDisplayed="); pw.print(startingDisplayed);
398                     pw.print(" startingMoved"); pw.println(startingMoved);
399         }
400     }
401 
402     @Override
toString()403     public String toString() {
404         if (stringName == null) {
405             StringBuilder sb = new StringBuilder();
406             sb.append("AppWindowToken{");
407             sb.append(Integer.toHexString(System.identityHashCode(this)));
408             sb.append(" token="); sb.append(token); sb.append('}');
409             stringName = sb.toString();
410         }
411         return stringName;
412     }
413 }