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