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