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