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 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.mSurfaceControl 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