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.input.InputApplicationHandle;
22 import com.android.server.wm.WindowManagerService.H;
23 
24 import android.content.pm.ActivityInfo;
25 import android.os.Message;
26 import android.os.RemoteException;
27 import android.util.Slog;
28 import android.view.IApplicationToken;
29 import android.view.View;
30 import android.view.WindowManager;
31 
32 import java.io.PrintWriter;
33 import java.util.ArrayList;
34 
35 class AppTokenList extends ArrayList<AppWindowToken> {
36 }
37 
38 /**
39  * Version of WindowToken that is specifically for a particular application (or
40  * really activity) that is displaying windows.
41  */
42 class AppWindowToken extends WindowToken {
43     // Non-null only for application tokens.
44     final IApplicationToken appToken;
45 
46     // All of the windows and child windows that are included in this
47     // application token.  Note this list is NOT sorted!
48     final WindowList allAppWindows = new WindowList();
49     final AppWindowAnimator mAppAnimator;
50 
51     final WindowAnimator mAnimator;
52 
53     final boolean voiceInteraction;
54 
55     Task mTask;
56     boolean appFullscreen;
57     int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
58     boolean layoutConfigChanges;
59     boolean showForAllUsers;
60 
61     // The input dispatching timeout for this application token in nanoseconds.
62     long inputDispatchingTimeoutNanos;
63 
64     // These are used for determining when all windows associated with
65     // an activity have been drawn, so they can be made visible together
66     // at the same time.
67     // initialize so that it doesn't match mTransactionSequence which is an int.
68     long lastTransactionSequence = Long.MIN_VALUE;
69     int numInterestingWindows;
70     int numDrawnWindows;
71     boolean inPendingTransaction;
72     boolean allDrawn;
73     // Set to true when this app creates a surface while in the middle of an animation. In that
74     // case do not clear allDrawn until the animation completes.
75     boolean deferClearAllDrawn;
76 
77     // Is this token going to be hidden in a little while?  If so, it
78     // won't be taken into account for setting the screen orientation.
79     boolean willBeHidden;
80 
81     // Is this window's surface needed?  This is almost like hidden, except
82     // it will sometimes be true a little earlier: when the token has
83     // been shown, but is still waiting for its app transition to execute
84     // before making its windows shown.
85     boolean hiddenRequested;
86 
87     // Have we told the window clients to hide themselves?
88     boolean clientHidden;
89 
90     // Last visibility state we reported to the app token.
91     boolean reportedVisible;
92 
93     // Last drawn state we reported to the app token.
94     boolean reportedDrawn;
95 
96     // Set to true when the token has been removed from the window mgr.
97     boolean removed;
98 
99     // Information about an application starting window if displayed.
100     StartingData startingData;
101     WindowState startingWindow;
102     View startingView;
103     boolean startingDisplayed;
104     boolean startingMoved;
105     boolean firstWindowDrawn;
106 
107     // Input application handle used by the input dispatcher.
108     final InputApplicationHandle mInputApplicationHandle;
109 
110     boolean mIsExiting;
111 
112     boolean mLaunchTaskBehind;
113     boolean mEnteringAnimation;
114 
AppWindowToken(WindowManagerService _service, IApplicationToken _token, boolean _voiceInteraction)115     AppWindowToken(WindowManagerService _service, IApplicationToken _token,
116             boolean _voiceInteraction) {
117         super(_service, _token.asBinder(),
118                 WindowManager.LayoutParams.TYPE_APPLICATION, true);
119         appWindowToken = this;
120         appToken = _token;
121         voiceInteraction = _voiceInteraction;
122         mInputApplicationHandle = new InputApplicationHandle(this);
123         mAnimator = service.mAnimator;
124         mAppAnimator = new AppWindowAnimator(this);
125     }
126 
sendAppVisibilityToClients()127     void sendAppVisibilityToClients() {
128         final int N = allAppWindows.size();
129         for (int i=0; i<N; i++) {
130             WindowState win = allAppWindows.get(i);
131             if (win == startingWindow && clientHidden) {
132                 // Don't hide the starting window.
133                 continue;
134             }
135             try {
136                 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
137                         "Setting visibility of " + win + ": " + (!clientHidden));
138                 win.mClient.dispatchAppVisibility(!clientHidden);
139             } catch (RemoteException e) {
140             }
141         }
142     }
143 
updateReportedVisibilityLocked()144     void updateReportedVisibilityLocked() {
145         if (appToken == null) {
146             return;
147         }
148 
149         int numInteresting = 0;
150         int numVisible = 0;
151         int numDrawn = 0;
152         boolean nowGone = true;
153 
154         if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
155                 "Update reported visibility: " + this);
156         final int N = allAppWindows.size();
157         for (int i=0; i<N; i++) {
158             WindowState win = allAppWindows.get(i);
159             if (win == startingWindow || win.mAppFreezing
160                     || win.mViewVisibility != View.VISIBLE
161                     || win.mAttrs.type == TYPE_APPLICATION_STARTING
162                     || win.mDestroying) {
163                 continue;
164             }
165             if (WindowManagerService.DEBUG_VISIBILITY) {
166                 Slog.v(WindowManagerService.TAG, "Win " + win + ": isDrawn="
167                         + win.isDrawnLw()
168                         + ", isAnimating=" + win.mWinAnimator.isAnimating());
169                 if (!win.isDrawnLw()) {
170                     Slog.v(WindowManagerService.TAG, "Not displayed: s=" + win.mWinAnimator.mSurfaceControl
171                             + " pv=" + win.mPolicyVisibility
172                             + " mDrawState=" + win.mWinAnimator.mDrawState
173                             + " ah=" + win.mAttachedHidden
174                             + " th="
175                             + (win.mAppToken != null
176                                     ? win.mAppToken.hiddenRequested : false)
177                             + " a=" + win.mWinAnimator.mAnimating);
178                 }
179             }
180             numInteresting++;
181             if (win.isDrawnLw()) {
182                 numDrawn++;
183                 if (!win.mWinAnimator.isAnimating()) {
184                     numVisible++;
185                 }
186                 nowGone = false;
187             } else if (win.mWinAnimator.isAnimating()) {
188                 nowGone = false;
189             }
190         }
191 
192         boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
193         boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
194         if (!nowGone) {
195             // If the app is not yet gone, then it can only become visible/drawn.
196             if (!nowDrawn) {
197                 nowDrawn = reportedDrawn;
198             }
199             if (!nowVisible) {
200                 nowVisible = reportedVisible;
201             }
202         }
203         if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "VIS " + this + ": interesting="
204                 + numInteresting + " visible=" + numVisible);
205         if (nowDrawn != reportedDrawn) {
206             if (nowDrawn) {
207                 Message m = service.mH.obtainMessage(
208                         H.REPORT_APPLICATION_TOKEN_DRAWN, this);
209                 service.mH.sendMessage(m);
210             }
211             reportedDrawn = nowDrawn;
212         }
213         if (nowVisible != reportedVisible) {
214             if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(
215                     WindowManagerService.TAG, "Visibility changed in " + this
216                     + ": vis=" + nowVisible);
217             reportedVisible = nowVisible;
218             Message m = service.mH.obtainMessage(
219                     H.REPORT_APPLICATION_TOKEN_WINDOWS,
220                     nowVisible ? 1 : 0,
221                     nowGone ? 1 : 0,
222                     this);
223             service.mH.sendMessage(m);
224         }
225     }
226 
findMainWindow()227     WindowState findMainWindow() {
228         int j = windows.size();
229         while (j > 0) {
230             j--;
231             WindowState win = windows.get(j);
232             if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
233                     || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
234                 return win;
235             }
236         }
237         return null;
238     }
239 
isVisible()240     boolean isVisible() {
241         final int N = allAppWindows.size();
242         for (int i=0; i<N; i++) {
243             WindowState win = allAppWindows.get(i);
244             if (!win.mAppFreezing
245                     && (win.mViewVisibility == View.VISIBLE ||
246                         (win.mWinAnimator.isAnimating() &&
247                                 !service.mAppTransition.isTransitionSet()))
248                     && !win.mDestroying && win.isDrawnLw()) {
249                 return true;
250             }
251         }
252         return false;
253     }
254 
removeAppFromTaskLocked()255     void removeAppFromTaskLocked() {
256         mIsExiting = false;
257         removeAllWindows();
258 
259         // Use local variable because removeAppToken will null out mTask.
260         final Task task = mTask;
261         if (task != null) {
262             if (!task.removeAppToken(this)) {
263                 Slog.e(WindowManagerService.TAG, "removeAppFromTaskLocked: token=" + this
264                         + " not found.");
265             }
266             task.mStack.mExitingAppTokens.remove(this);
267         }
268     }
269 
270     @Override
removeAllWindows()271     void removeAllWindows() {
272         for (int winNdx = allAppWindows.size() - 1; winNdx >= 0;
273                 // removeWindowLocked at bottom of loop may remove multiple entries from
274                 // allAppWindows if the window to be removed has child windows. It also may
275                 // not remove any windows from allAppWindows at all if win is exiting and
276                 // currently animating away. This ensures that winNdx is monotonically decreasing
277                 // and never beyond allAppWindows bounds.
278                 winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) {
279             WindowState win = allAppWindows.get(winNdx);
280             if (WindowManagerService.DEBUG_WINDOW_MOVEMENT) {
281                 Slog.w(WindowManagerService.TAG, "removeAllWindows: removing win=" + win);
282             }
283 
284             service.removeWindowLocked(win);
285         }
286         allAppWindows.clear();
287         windows.clear();
288     }
289 
290     @Override
dump(PrintWriter pw, String prefix)291     void dump(PrintWriter pw, String prefix) {
292         super.dump(pw, prefix);
293         if (appToken != null) {
294             pw.print(prefix); pw.print("app=true voiceInteraction="); pw.println(voiceInteraction);
295         }
296         if (allAppWindows.size() > 0) {
297             pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
298         }
299         pw.print(prefix); pw.print("task="); pw.println(mTask);
300         pw.print(prefix); pw.print(" appFullscreen="); pw.print(appFullscreen);
301                 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
302         pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
303                 pw.print(" clientHidden="); pw.print(clientHidden);
304                 pw.print(" willBeHidden="); pw.print(willBeHidden);
305                 pw.print(" reportedDrawn="); pw.print(reportedDrawn);
306                 pw.print(" reportedVisible="); pw.println(reportedVisible);
307         if (paused) {
308             pw.print(prefix); pw.print("paused="); pw.println(paused);
309         }
310         if (numInterestingWindows != 0 || numDrawnWindows != 0
311                 || allDrawn || mAppAnimator.allDrawn) {
312             pw.print(prefix); pw.print("numInterestingWindows=");
313                     pw.print(numInterestingWindows);
314                     pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
315                     pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
316                     pw.print(" allDrawn="); pw.print(allDrawn);
317                     pw.print(" (animator="); pw.print(mAppAnimator.allDrawn);
318                     pw.println(")");
319         }
320         if (inPendingTransaction) {
321             pw.print(prefix); pw.print("inPendingTransaction=");
322                     pw.println(inPendingTransaction);
323         }
324         if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
325             pw.print(prefix); pw.print("startingData="); pw.print(startingData);
326                     pw.print(" removed="); pw.print(removed);
327                     pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
328                     pw.print(" mIsExiting="); pw.println(mIsExiting);
329         }
330         if (startingWindow != null || startingView != null
331                 || startingDisplayed || startingMoved) {
332             pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
333                     pw.print(" startingView="); pw.print(startingView);
334                     pw.print(" startingDisplayed="); pw.print(startingDisplayed);
335                     pw.print(" startingMoved"); pw.println(startingMoved);
336         }
337     }
338 
339     @Override
toString()340     public String toString() {
341         if (stringName == null) {
342             StringBuilder sb = new StringBuilder();
343             sb.append("AppWindowToken{");
344             sb.append(Integer.toHexString(System.identityHashCode(this)));
345             sb.append(" token="); sb.append(token); sb.append('}');
346             stringName = sb.toString();
347         }
348         return stringName;
349     }
350 }
351