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.FIRST_SUB_WINDOW; 20 import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW; 21 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; 22 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 23 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 24 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 25 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 26 27 import com.android.server.wm.WindowManagerService.H; 28 29 import android.content.res.Configuration; 30 import android.graphics.Matrix; 31 import android.graphics.PixelFormat; 32 import android.graphics.Rect; 33 import android.graphics.RectF; 34 import android.graphics.Region; 35 import android.os.IBinder; 36 import android.os.RemoteException; 37 import android.util.Slog; 38 import android.view.Gravity; 39 import android.view.IApplicationToken; 40 import android.view.IWindow; 41 import android.view.InputChannel; 42 import android.view.Surface; 43 import android.view.View; 44 import android.view.ViewTreeObserver; 45 import android.view.WindowManager; 46 import android.view.WindowManagerPolicy; 47 import android.view.WindowManager.LayoutParams; 48 import android.view.animation.Animation; 49 import android.view.animation.Transformation; 50 51 import java.io.PrintWriter; 52 import java.util.ArrayList; 53 54 /** 55 * A window in the window manager. 56 */ 57 final class WindowState implements WindowManagerPolicy.WindowState { 58 static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY; 59 static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS; 60 static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS; 61 static final boolean SHOW_SURFACE_ALLOC = WindowManagerService.SHOW_SURFACE_ALLOC; 62 63 final WindowManagerService mService; 64 final Session mSession; 65 final IWindow mClient; 66 WindowToken mToken; 67 WindowToken mRootToken; 68 AppWindowToken mAppToken; 69 AppWindowToken mTargetAppToken; 70 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams(); 71 final DeathRecipient mDeathRecipient; 72 final WindowState mAttachedWindow; 73 final ArrayList<WindowState> mChildWindows = new ArrayList<WindowState>(); 74 final int mBaseLayer; 75 final int mSubLayer; 76 final boolean mLayoutAttached; 77 final boolean mIsImWindow; 78 final boolean mIsWallpaper; 79 final boolean mIsFloatingLayer; 80 int mSeq; 81 boolean mEnforceSizeCompat; 82 int mViewVisibility; 83 int mSystemUiVisibility; 84 boolean mPolicyVisibility = true; 85 boolean mPolicyVisibilityAfterAnim = true; 86 boolean mAppFreezing; 87 Surface mSurface; 88 boolean mReportDestroySurface; 89 boolean mSurfacePendingDestroy; 90 boolean mAttachedHidden; // is our parent window hidden? 91 boolean mLastHidden; // was this window last hidden? 92 boolean mWallpaperVisible; // for wallpaper, what was last vis report? 93 94 /** 95 * The window size that was requested by the application. These are in 96 * the application's coordinate space (without compatibility scale applied). 97 */ 98 int mRequestedWidth; 99 int mRequestedHeight; 100 101 int mLayer; 102 int mAnimLayer; 103 int mLastLayer; 104 boolean mHaveFrame; 105 boolean mObscured; 106 boolean mTurnOnScreen; 107 108 int mLayoutSeq = -1; 109 110 Configuration mConfiguration = null; 111 112 /** 113 * Actual frame shown on-screen (may be modified by animation). These 114 * are in the screen's coordinate space (WITH the compatibility scale 115 * applied). 116 */ 117 final RectF mShownFrame = new RectF(); 118 119 /** 120 * Set when we have changed the size of the surface, to know that 121 * we must tell them application to resize (and thus redraw itself). 122 */ 123 boolean mSurfaceResized; 124 125 /** 126 * Insets that determine the actually visible area. These are in the application's 127 * coordinate space (without compatibility scale applied). 128 */ 129 final Rect mVisibleInsets = new Rect(); 130 final Rect mLastVisibleInsets = new Rect(); 131 boolean mVisibleInsetsChanged; 132 133 /** 134 * Insets that are covered by system windows. These are in the application's 135 * coordinate space (without compatibility scale applied). 136 */ 137 final Rect mContentInsets = new Rect(); 138 final Rect mLastContentInsets = new Rect(); 139 boolean mContentInsetsChanged; 140 141 /** 142 * Set to true if we are waiting for this window to receive its 143 * given internal insets before laying out other windows based on it. 144 */ 145 boolean mGivenInsetsPending; 146 147 /** 148 * These are the content insets that were given during layout for 149 * this window, to be applied to windows behind it. 150 */ 151 final Rect mGivenContentInsets = new Rect(); 152 153 /** 154 * These are the visible insets that were given during layout for 155 * this window, to be applied to windows behind it. 156 */ 157 final Rect mGivenVisibleInsets = new Rect(); 158 159 /** 160 * This is the given touchable area relative to the window frame, or null if none. 161 */ 162 final Region mGivenTouchableRegion = new Region(); 163 164 /** 165 * Flag indicating whether the touchable region should be adjusted by 166 * the visible insets; if false the area outside the visible insets is 167 * NOT touchable, so we must use those to adjust the frame during hit 168 * tests. 169 */ 170 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; 171 172 // Current transformation being applied. 173 boolean mHaveMatrix; 174 float mGlobalScale=1; 175 float mInvGlobalScale=1; 176 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1; 177 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1; 178 float mHScale=1, mVScale=1; 179 float mLastHScale=1, mLastVScale=1; 180 final Matrix mTmpMatrix = new Matrix(); 181 182 // "Real" frame that the application sees, in display coordinate space. 183 final Rect mFrame = new Rect(); 184 final Rect mLastFrame = new Rect(); 185 // Frame that is scaled to the application's coordinate space when in 186 // screen size compatibility mode. 187 final Rect mCompatFrame = new Rect(); 188 189 final Rect mContainingFrame = new Rect(); 190 final Rect mDisplayFrame = new Rect(); 191 final Rect mContentFrame = new Rect(); 192 final Rect mParentFrame = new Rect(); 193 final Rect mVisibleFrame = new Rect(); 194 195 boolean mContentChanged; 196 197 float mShownAlpha = 1; 198 float mAlpha = 1; 199 float mLastAlpha = 1; 200 201 // Set to true if, when the window gets displayed, it should perform 202 // an enter animation. 203 boolean mEnterAnimationPending; 204 205 // Currently running animation. 206 boolean mAnimating; 207 boolean mLocalAnimating; 208 Animation mAnimation; 209 boolean mAnimationIsEntrance; 210 boolean mHasTransformation; 211 boolean mHasLocalTransformation; 212 final Transformation mTransformation = new Transformation(); 213 214 // If a window showing a wallpaper: the requested offset for the 215 // wallpaper; if a wallpaper window: the currently applied offset. 216 float mWallpaperX = -1; 217 float mWallpaperY = -1; 218 219 // If a window showing a wallpaper: what fraction of the offset 220 // range corresponds to a full virtual screen. 221 float mWallpaperXStep = -1; 222 float mWallpaperYStep = -1; 223 224 // Wallpaper windows: pixels offset based on above variables. 225 int mXOffset; 226 int mYOffset; 227 228 // This is set after IWindowSession.relayout() has been called at 229 // least once for the window. It allows us to detect the situation 230 // where we don't yet have a surface, but should have one soon, so 231 // we can give the window focus before waiting for the relayout. 232 boolean mRelayoutCalled; 233 234 // This is set after the Surface has been created but before the 235 // window has been drawn. During this time the surface is hidden. 236 boolean mDrawPending; 237 238 // This is set after the window has finished drawing for the first 239 // time but before its surface is shown. The surface will be 240 // displayed when the next layout is run. 241 boolean mCommitDrawPending; 242 243 // This is set during the time after the window's drawing has been 244 // committed, and before its surface is actually shown. It is used 245 // to delay showing the surface until all windows in a token are ready 246 // to be shown. 247 boolean mReadyToShow; 248 249 // Set when the window has been shown in the screen the first time. 250 boolean mHasDrawn; 251 252 // Currently running an exit animation? 253 boolean mExiting; 254 255 // Currently on the mDestroySurface list? 256 boolean mDestroying; 257 258 // Completely remove from window manager after exit animation? 259 boolean mRemoveOnExit; 260 261 // Set when the orientation is changing and this window has not yet 262 // been updated for the new orientation. 263 boolean mOrientationChanging; 264 265 // Is this window now (or just being) removed? 266 boolean mRemoved; 267 268 // Temp for keeping track of windows that have been removed when 269 // rebuilding window list. 270 boolean mRebuilding; 271 272 // For debugging, this is the last information given to the surface flinger. 273 boolean mSurfaceShown; 274 float mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH; 275 int mSurfaceLayer; 276 float mSurfaceAlpha; 277 278 // Input channel and input window handle used by the input dispatcher. 279 final InputWindowHandle mInputWindowHandle; 280 InputChannel mInputChannel; 281 282 // Used to improve performance of toString() 283 String mStringNameCache; 284 CharSequence mLastTitle; 285 boolean mWasPaused; 286 WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, WindowState attachedWindow, int seq, WindowManager.LayoutParams a, int viewVisibility)287 WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, 288 WindowState attachedWindow, int seq, WindowManager.LayoutParams a, 289 int viewVisibility) { 290 mService = service; 291 mSession = s; 292 mClient = c; 293 mToken = token; 294 mAttrs.copyFrom(a); 295 mViewVisibility = viewVisibility; 296 DeathRecipient deathRecipient = new DeathRecipient(); 297 mAlpha = a.alpha; 298 mSeq = seq; 299 mEnforceSizeCompat = (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0; 300 if (WindowManagerService.localLOGV) Slog.v( 301 WindowManagerService.TAG, "Window " + this + " client=" + c.asBinder() 302 + " token=" + token + " (" + mAttrs.token + ")"); 303 try { 304 c.asBinder().linkToDeath(deathRecipient, 0); 305 } catch (RemoteException e) { 306 mDeathRecipient = null; 307 mAttachedWindow = null; 308 mLayoutAttached = false; 309 mIsImWindow = false; 310 mIsWallpaper = false; 311 mIsFloatingLayer = false; 312 mBaseLayer = 0; 313 mSubLayer = 0; 314 mInputWindowHandle = null; 315 return; 316 } 317 mDeathRecipient = deathRecipient; 318 319 if ((mAttrs.type >= FIRST_SUB_WINDOW && 320 mAttrs.type <= LAST_SUB_WINDOW)) { 321 // The multiplier here is to reserve space for multiple 322 // windows in the same type layer. 323 mBaseLayer = mService.mPolicy.windowTypeToLayerLw( 324 attachedWindow.mAttrs.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER 325 + WindowManagerService.TYPE_LAYER_OFFSET; 326 mSubLayer = mService.mPolicy.subWindowTypeToLayerLw(a.type); 327 mAttachedWindow = attachedWindow; 328 if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Adding " + this + " to " + mAttachedWindow); 329 mAttachedWindow.mChildWindows.add(this); 330 mLayoutAttached = mAttrs.type != 331 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 332 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD 333 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG; 334 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER; 335 mIsFloatingLayer = mIsImWindow || mIsWallpaper; 336 } else { 337 // The multiplier here is to reserve space for multiple 338 // windows in the same type layer. 339 mBaseLayer = mService.mPolicy.windowTypeToLayerLw(a.type) 340 * WindowManagerService.TYPE_LAYER_MULTIPLIER 341 + WindowManagerService.TYPE_LAYER_OFFSET; 342 mSubLayer = 0; 343 mAttachedWindow = null; 344 mLayoutAttached = false; 345 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD 346 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG; 347 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER; 348 mIsFloatingLayer = mIsImWindow || mIsWallpaper; 349 } 350 351 WindowState appWin = this; 352 while (appWin.mAttachedWindow != null) { 353 appWin = mAttachedWindow; 354 } 355 WindowToken appToken = appWin.mToken; 356 while (appToken.appWindowToken == null) { 357 WindowToken parent = mService.mTokenMap.get(appToken.token); 358 if (parent == null || appToken == parent) { 359 break; 360 } 361 appToken = parent; 362 } 363 mRootToken = appToken; 364 mAppToken = appToken.appWindowToken; 365 366 mSurface = null; 367 mRequestedWidth = 0; 368 mRequestedHeight = 0; 369 mXOffset = 0; 370 mYOffset = 0; 371 mLayer = 0; 372 mAnimLayer = 0; 373 mLastLayer = 0; 374 mInputWindowHandle = new InputWindowHandle( 375 mAppToken != null ? mAppToken.mInputApplicationHandle : null, this); 376 } 377 attach()378 void attach() { 379 if (WindowManagerService.localLOGV) Slog.v( 380 WindowManagerService.TAG, "Attaching " + this + " token=" + mToken 381 + ", list=" + mToken.windows); 382 mSession.windowAddedLocked(); 383 } 384 computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf)385 public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) { 386 mHaveFrame = true; 387 388 final Rect container = mContainingFrame; 389 container.set(pf); 390 391 final Rect display = mDisplayFrame; 392 display.set(df); 393 394 final int pw = container.right - container.left; 395 final int ph = container.bottom - container.top; 396 397 int w,h; 398 if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0) { 399 if (mAttrs.width < 0) { 400 w = pw; 401 } else if (mEnforceSizeCompat) { 402 w = (int)(mAttrs.width * mGlobalScale + .5f); 403 } else { 404 w = mAttrs.width; 405 } 406 if (mAttrs.height < 0) { 407 h = ph; 408 } else if (mEnforceSizeCompat) { 409 h = (int)(mAttrs.height * mGlobalScale + .5f); 410 } else { 411 h = mAttrs.height; 412 } 413 } else { 414 if (mAttrs.width == WindowManager.LayoutParams.MATCH_PARENT) { 415 w = pw; 416 } else if (mEnforceSizeCompat) { 417 w = (int)(mRequestedWidth * mGlobalScale + .5f); 418 } else { 419 w = mRequestedWidth; 420 } 421 if (mAttrs.height == WindowManager.LayoutParams.MATCH_PARENT) { 422 h = ph; 423 } else if (mEnforceSizeCompat) { 424 h = (int)(mRequestedHeight * mGlobalScale + .5f); 425 } else { 426 h = mRequestedHeight; 427 } 428 } 429 430 if (!mParentFrame.equals(pf)) { 431 //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame 432 // + " to " + pf); 433 mParentFrame.set(pf); 434 mContentChanged = true; 435 } 436 437 final Rect content = mContentFrame; 438 content.set(cf); 439 440 final Rect visible = mVisibleFrame; 441 visible.set(vf); 442 443 final Rect frame = mFrame; 444 final int fw = frame.width(); 445 final int fh = frame.height(); 446 447 //System.out.println("In: w=" + w + " h=" + h + " container=" + 448 // container + " x=" + mAttrs.x + " y=" + mAttrs.y); 449 450 float x, y; 451 if (mEnforceSizeCompat) { 452 x = mAttrs.x * mGlobalScale; 453 y = mAttrs.y * mGlobalScale; 454 } else { 455 x = mAttrs.x; 456 y = mAttrs.y; 457 } 458 459 Gravity.apply(mAttrs.gravity, w, h, container, 460 (int) (x + mAttrs.horizontalMargin * pw), 461 (int) (y + mAttrs.verticalMargin * ph), frame); 462 463 //System.out.println("Out: " + mFrame); 464 465 // Now make sure the window fits in the overall display. 466 Gravity.applyDisplay(mAttrs.gravity, df, frame); 467 468 // Make sure the content and visible frames are inside of the 469 // final window frame. 470 if (content.left < frame.left) content.left = frame.left; 471 if (content.top < frame.top) content.top = frame.top; 472 if (content.right > frame.right) content.right = frame.right; 473 if (content.bottom > frame.bottom) content.bottom = frame.bottom; 474 if (visible.left < frame.left) visible.left = frame.left; 475 if (visible.top < frame.top) visible.top = frame.top; 476 if (visible.right > frame.right) visible.right = frame.right; 477 if (visible.bottom > frame.bottom) visible.bottom = frame.bottom; 478 479 final Rect contentInsets = mContentInsets; 480 contentInsets.left = content.left-frame.left; 481 contentInsets.top = content.top-frame.top; 482 contentInsets.right = frame.right-content.right; 483 contentInsets.bottom = frame.bottom-content.bottom; 484 485 final Rect visibleInsets = mVisibleInsets; 486 visibleInsets.left = visible.left-frame.left; 487 visibleInsets.top = visible.top-frame.top; 488 visibleInsets.right = frame.right-visible.right; 489 visibleInsets.bottom = frame.bottom-visible.bottom; 490 491 mCompatFrame.set(frame); 492 if (mEnforceSizeCompat) { 493 // If there is a size compatibility scale being applied to the 494 // window, we need to apply this to its insets so that they are 495 // reported to the app in its coordinate space. 496 contentInsets.scale(mInvGlobalScale); 497 visibleInsets.scale(mInvGlobalScale); 498 499 // Also the scaled frame that we report to the app needs to be 500 // adjusted to be in its coordinate space. 501 mCompatFrame.scale(mInvGlobalScale); 502 } 503 504 if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) { 505 mService.updateWallpaperOffsetLocked(this, 506 mService.mAppDisplayWidth, mService.mAppDisplayHeight, false); 507 } 508 509 if (WindowManagerService.localLOGV) { 510 //if ("com.google.android.youtube".equals(mAttrs.packageName) 511 // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { 512 Slog.v(WindowManagerService.TAG, "Resolving (mRequestedWidth=" 513 + mRequestedWidth + ", mRequestedheight=" 514 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph 515 + "): frame=" + mFrame.toShortString() 516 + " ci=" + contentInsets.toShortString() 517 + " vi=" + visibleInsets.toShortString()); 518 //} 519 } 520 } 521 getFrameLw()522 public Rect getFrameLw() { 523 return mFrame; 524 } 525 getShownFrameLw()526 public RectF getShownFrameLw() { 527 return mShownFrame; 528 } 529 getDisplayFrameLw()530 public Rect getDisplayFrameLw() { 531 return mDisplayFrame; 532 } 533 getContentFrameLw()534 public Rect getContentFrameLw() { 535 return mContentFrame; 536 } 537 getVisibleFrameLw()538 public Rect getVisibleFrameLw() { 539 return mVisibleFrame; 540 } 541 getGivenInsetsPendingLw()542 public boolean getGivenInsetsPendingLw() { 543 return mGivenInsetsPending; 544 } 545 getGivenContentInsetsLw()546 public Rect getGivenContentInsetsLw() { 547 return mGivenContentInsets; 548 } 549 getGivenVisibleInsetsLw()550 public Rect getGivenVisibleInsetsLw() { 551 return mGivenVisibleInsets; 552 } 553 getAttrs()554 public WindowManager.LayoutParams getAttrs() { 555 return mAttrs; 556 } 557 getSystemUiVisibility()558 public int getSystemUiVisibility() { 559 return mSystemUiVisibility; 560 } 561 getSurfaceLayer()562 public int getSurfaceLayer() { 563 return mLayer; 564 } 565 getAppToken()566 public IApplicationToken getAppToken() { 567 return mAppToken != null ? mAppToken.appToken : null; 568 } 569 getInputDispatchingTimeoutNanos()570 public long getInputDispatchingTimeoutNanos() { 571 return mAppToken != null 572 ? mAppToken.inputDispatchingTimeoutNanos 573 : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 574 } 575 hasAppShownWindows()576 public boolean hasAppShownWindows() { 577 return mAppToken != null ? mAppToken.firstWindowDrawn : false; 578 } 579 setAnimation(Animation anim)580 public void setAnimation(Animation anim) { 581 if (WindowManagerService.localLOGV) Slog.v( 582 WindowManagerService.TAG, "Setting animation in " + this + ": " + anim); 583 mAnimating = false; 584 mLocalAnimating = false; 585 mAnimation = anim; 586 mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION); 587 mAnimation.scaleCurrentDuration(mService.mWindowAnimationScale); 588 } 589 clearAnimation()590 public void clearAnimation() { 591 if (mAnimation != null) { 592 mAnimating = true; 593 mLocalAnimating = false; 594 mAnimation.cancel(); 595 mAnimation = null; 596 } 597 } 598 createSurfaceLocked()599 Surface createSurfaceLocked() { 600 if (mSurface == null) { 601 mReportDestroySurface = false; 602 mSurfacePendingDestroy = false; 603 Slog.i(WindowManagerService.TAG, "createSurface " + this + ": DRAW NOW PENDING"); 604 mDrawPending = true; 605 mCommitDrawPending = false; 606 mReadyToShow = false; 607 if (mAppToken != null) { 608 mAppToken.allDrawn = false; 609 } 610 611 mService.makeWindowFreezingScreenIfNeededLocked(this); 612 613 int flags = 0; 614 615 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) { 616 flags |= Surface.SECURE; 617 } 618 if (DEBUG_VISIBILITY) Slog.v( 619 WindowManagerService.TAG, "Creating surface in session " 620 + mSession.mSurfaceSession + " window " + this 621 + " w=" + mCompatFrame.width() 622 + " h=" + mCompatFrame.height() + " format=" 623 + mAttrs.format + " flags=" + flags); 624 625 int w = mCompatFrame.width(); 626 int h = mCompatFrame.height(); 627 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) { 628 // for a scaled surface, we always want the requested 629 // size. 630 w = mRequestedWidth; 631 h = mRequestedHeight; 632 } 633 634 // Something is wrong and SurfaceFlinger will not like this, 635 // try to revert to sane values 636 if (w <= 0) w = 1; 637 if (h <= 0) h = 1; 638 639 mSurfaceShown = false; 640 mSurfaceLayer = 0; 641 mSurfaceAlpha = 1; 642 mSurfaceX = 0; 643 mSurfaceY = 0; 644 mSurfaceW = w; 645 mSurfaceH = h; 646 try { 647 final boolean isHwAccelerated = (mAttrs.flags & 648 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0; 649 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : mAttrs.format; 650 if (!PixelFormat.formatHasAlpha(mAttrs.format)) { 651 flags |= Surface.OPAQUE; 652 } 653 mSurface = new Surface( 654 mSession.mSurfaceSession, mSession.mPid, 655 mAttrs.getTitle().toString(), 656 0, w, h, format, flags); 657 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, 658 " CREATE SURFACE " 659 + mSurface + " IN SESSION " 660 + mSession.mSurfaceSession 661 + ": pid=" + mSession.mPid + " format=" 662 + mAttrs.format + " flags=0x" 663 + Integer.toHexString(flags) 664 + " / " + this); 665 } catch (Surface.OutOfResourcesException e) { 666 Slog.w(WindowManagerService.TAG, "OutOfResourcesException creating surface"); 667 mService.reclaimSomeSurfaceMemoryLocked(this, "create", true); 668 return null; 669 } catch (Exception e) { 670 Slog.e(WindowManagerService.TAG, "Exception creating surface", e); 671 return null; 672 } 673 674 if (WindowManagerService.localLOGV) Slog.v( 675 WindowManagerService.TAG, "Got surface: " + mSurface 676 + ", set left=" + mFrame.left + " top=" + mFrame.top 677 + ", animLayer=" + mAnimLayer); 678 if (SHOW_LIGHT_TRANSACTIONS) { 679 Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION createSurfaceLocked"); 680 WindowManagerService.logSurface(this, "CREATE pos=(" + mFrame.left 681 + "," + mFrame.top + ") (" + 682 mCompatFrame.width() + "x" + mCompatFrame.height() + "), layer=" + 683 mAnimLayer + " HIDE", null); 684 } 685 Surface.openTransaction(); 686 try { 687 try { 688 mSurfaceX = mFrame.left + mXOffset; 689 mSurfaceY = mFrame.top + mYOffset; 690 mSurface.setPosition(mSurfaceX, mSurfaceY); 691 mSurfaceLayer = mAnimLayer; 692 mSurface.setLayer(mAnimLayer); 693 mSurfaceShown = false; 694 mSurface.hide(); 695 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) { 696 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(this, "DITHER", null); 697 mSurface.setFlags(Surface.SURFACE_DITHER, 698 Surface.SURFACE_DITHER); 699 } 700 } catch (RuntimeException e) { 701 Slog.w(WindowManagerService.TAG, "Error creating surface in " + w, e); 702 mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true); 703 } 704 mLastHidden = true; 705 } finally { 706 Surface.closeTransaction(); 707 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG, 708 "<<< CLOSE TRANSACTION createSurfaceLocked"); 709 } 710 if (WindowManagerService.localLOGV) Slog.v( 711 WindowManagerService.TAG, "Created surface " + this); 712 } 713 return mSurface; 714 } 715 destroySurfaceLocked()716 void destroySurfaceLocked() { 717 if (mAppToken != null && this == mAppToken.startingWindow) { 718 mAppToken.startingDisplayed = false; 719 } 720 721 if (mSurface != null) { 722 mDrawPending = false; 723 mCommitDrawPending = false; 724 mReadyToShow = false; 725 726 int i = mChildWindows.size(); 727 while (i > 0) { 728 i--; 729 WindowState c = mChildWindows.get(i); 730 c.mAttachedHidden = true; 731 } 732 733 if (mReportDestroySurface) { 734 mReportDestroySurface = false; 735 mSurfacePendingDestroy = true; 736 try { 737 mClient.dispatchGetNewSurface(); 738 // We'll really destroy on the next time around. 739 return; 740 } catch (RemoteException e) { 741 } 742 } 743 744 try { 745 if (DEBUG_VISIBILITY) { 746 RuntimeException e = null; 747 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 748 e = new RuntimeException(); 749 e.fillInStackTrace(); 750 } 751 Slog.w(WindowManagerService.TAG, "Window " + this + " destroying surface " 752 + mSurface + ", session " + mSession, e); 753 } 754 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { 755 RuntimeException e = null; 756 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 757 e = new RuntimeException(); 758 e.fillInStackTrace(); 759 } 760 WindowManagerService.logSurface(this, "DESTROY", e); 761 } 762 mSurface.destroy(); 763 } catch (RuntimeException e) { 764 Slog.w(WindowManagerService.TAG, "Exception thrown when destroying Window " + this 765 + " surface " + mSurface + " session " + mSession 766 + ": " + e.toString()); 767 } 768 769 mSurfaceShown = false; 770 mSurface = null; 771 } 772 } 773 finishDrawingLocked()774 boolean finishDrawingLocked() { 775 if (mDrawPending) { 776 if (SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) Slog.v( 777 WindowManagerService.TAG, "finishDrawingLocked: " + this + " in " + mSurface); 778 mCommitDrawPending = true; 779 mDrawPending = false; 780 return true; 781 } 782 return false; 783 } 784 785 // This must be called while inside a transaction. commitFinishDrawingLocked(long currentTime)786 boolean commitFinishDrawingLocked(long currentTime) { 787 //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface); 788 if (!mCommitDrawPending) { 789 return false; 790 } 791 mCommitDrawPending = false; 792 mReadyToShow = true; 793 final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING; 794 final AppWindowToken atoken = mAppToken; 795 if (atoken == null || atoken.allDrawn || starting) { 796 performShowLocked(); 797 } 798 return true; 799 } 800 801 // This must be called while inside a transaction. performShowLocked()802 boolean performShowLocked() { 803 if (DEBUG_VISIBILITY) { 804 RuntimeException e = null; 805 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 806 e = new RuntimeException(); 807 e.fillInStackTrace(); 808 } 809 Slog.v(WindowManagerService.TAG, "performShow on " + this 810 + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay() 811 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e); 812 } 813 if (mReadyToShow && isReadyForDisplay()) { 814 if (SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) WindowManagerService.logSurface(this, 815 "SHOW (performShowLocked)", null); 816 if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Showing " + this 817 + " during animation: policyVis=" + mPolicyVisibility 818 + " attHidden=" + mAttachedHidden 819 + " tok.hiddenRequested=" 820 + (mAppToken != null ? mAppToken.hiddenRequested : false) 821 + " tok.hidden=" 822 + (mAppToken != null ? mAppToken.hidden : false) 823 + " animating=" + mAnimating 824 + " tok animating=" 825 + (mAppToken != null ? mAppToken.animating : false)); 826 if (!mService.showSurfaceRobustlyLocked(this)) { 827 return false; 828 } 829 mLastAlpha = -1; 830 mHasDrawn = true; 831 mLastHidden = false; 832 mReadyToShow = false; 833 mService.enableScreenIfNeededLocked(); 834 835 mService.applyEnterAnimationLocked(this); 836 837 int i = mChildWindows.size(); 838 while (i > 0) { 839 i--; 840 WindowState c = mChildWindows.get(i); 841 if (c.mAttachedHidden) { 842 c.mAttachedHidden = false; 843 if (c.mSurface != null) { 844 c.performShowLocked(); 845 // It hadn't been shown, which means layout not 846 // performed on it, so now we want to make sure to 847 // do a layout. If called from within the transaction 848 // loop, this will cause it to restart with a new 849 // layout. 850 mService.mLayoutNeeded = true; 851 } 852 } 853 } 854 855 if (mAttrs.type != TYPE_APPLICATION_STARTING 856 && mAppToken != null) { 857 mAppToken.firstWindowDrawn = true; 858 859 if (mAppToken.startingData != null) { 860 if (WindowManagerService.DEBUG_STARTING_WINDOW || WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG, 861 "Finish starting " + mToken 862 + ": first real window is shown, no animation"); 863 // If this initial window is animating, stop it -- we 864 // will do an animation to reveal it from behind the 865 // starting window, so there is no need for it to also 866 // be doing its own stuff. 867 if (mAnimation != null) { 868 mAnimation.cancel(); 869 mAnimation = null; 870 // Make sure we clean up the animation. 871 mAnimating = true; 872 } 873 mService.mFinishedStarting.add(mAppToken); 874 mService.mH.sendEmptyMessage(H.FINISHED_STARTING); 875 } 876 mAppToken.updateReportedVisibilityLocked(); 877 } 878 } 879 return true; 880 } 881 882 // This must be called while inside a transaction. Returns true if 883 // there is more animation to run. stepAnimationLocked(long currentTime, int dw, int dh)884 boolean stepAnimationLocked(long currentTime, int dw, int dh) { 885 if (!mService.mDisplayFrozen && mService.mPolicy.isScreenOnFully()) { 886 // We will run animations as long as the display isn't frozen. 887 888 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) { 889 mHasTransformation = true; 890 mHasLocalTransformation = true; 891 if (!mLocalAnimating) { 892 if (WindowManagerService.DEBUG_ANIM) Slog.v( 893 WindowManagerService.TAG, "Starting animation in " + this + 894 " @ " + currentTime + ": ww=" + mFrame.width() + 895 " wh=" + mFrame.height() + 896 " dw=" + dw + " dh=" + dh + " scale=" + mService.mWindowAnimationScale); 897 mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh); 898 mAnimation.setStartTime(currentTime); 899 mLocalAnimating = true; 900 mAnimating = true; 901 } 902 mTransformation.clear(); 903 final boolean more = mAnimation.getTransformation( 904 currentTime, mTransformation); 905 if (WindowManagerService.DEBUG_ANIM) Slog.v( 906 WindowManagerService.TAG, "Stepped animation in " + this + 907 ": more=" + more + ", xform=" + mTransformation); 908 if (more) { 909 // we're not done! 910 return true; 911 } 912 if (WindowManagerService.DEBUG_ANIM) Slog.v( 913 WindowManagerService.TAG, "Finished animation in " + this + 914 " @ " + currentTime); 915 916 if (mAnimation != null) { 917 mAnimation.cancel(); 918 mAnimation = null; 919 } 920 //WindowManagerService.this.dump(); 921 } 922 mHasLocalTransformation = false; 923 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null 924 && mAppToken.animation != null) { 925 // When our app token is animating, we kind-of pretend like 926 // we are as well. Note the mLocalAnimating mAnimationIsEntrance 927 // part of this check means that we will only do this if 928 // our window is not currently exiting, or it is not 929 // locally animating itself. The idea being that one that 930 // is exiting and doing a local animation should be removed 931 // once that animation is done. 932 mAnimating = true; 933 mHasTransformation = true; 934 mTransformation.clear(); 935 return false; 936 } else if (mHasTransformation) { 937 // Little trick to get through the path below to act like 938 // we have finished an animation. 939 mAnimating = true; 940 } else if (isAnimating()) { 941 mAnimating = true; 942 } 943 } else if (mAnimation != null) { 944 // If the display is frozen, and there is a pending animation, 945 // clear it and make sure we run the cleanup code. 946 mAnimating = true; 947 mLocalAnimating = true; 948 mAnimation.cancel(); 949 mAnimation = null; 950 } 951 952 if (!mAnimating && !mLocalAnimating) { 953 return false; 954 } 955 956 if (WindowManagerService.DEBUG_ANIM) Slog.v( 957 WindowManagerService.TAG, "Animation done in " + this + ": exiting=" + mExiting 958 + ", reportedVisible=" 959 + (mAppToken != null ? mAppToken.reportedVisible : false)); 960 961 mAnimating = false; 962 mLocalAnimating = false; 963 if (mAnimation != null) { 964 mAnimation.cancel(); 965 mAnimation = null; 966 } 967 mAnimLayer = mLayer; 968 if (mIsImWindow) { 969 mAnimLayer += mService.mInputMethodAnimLayerAdjustment; 970 } else if (mIsWallpaper) { 971 mAnimLayer += mService.mWallpaperAnimLayerAdjustment; 972 } 973 if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Stepping win " + this 974 + " anim layer: " + mAnimLayer); 975 mHasTransformation = false; 976 mHasLocalTransformation = false; 977 if (mPolicyVisibility != mPolicyVisibilityAfterAnim) { 978 if (DEBUG_VISIBILITY) { 979 Slog.v(WindowManagerService.TAG, "Policy visibility changing after anim in " + this + ": " 980 + mPolicyVisibilityAfterAnim); 981 } 982 mPolicyVisibility = mPolicyVisibilityAfterAnim; 983 mService.mLayoutNeeded = true; 984 if (!mPolicyVisibility) { 985 if (mService.mCurrentFocus == this) { 986 mService.mFocusMayChange = true; 987 } 988 // Window is no longer visible -- make sure if we were waiting 989 // for it to be displayed before enabling the display, that 990 // we allow the display to be enabled now. 991 mService.enableScreenIfNeededLocked(); 992 } 993 } 994 mTransformation.clear(); 995 if (mHasDrawn 996 && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING 997 && mAppToken != null 998 && mAppToken.firstWindowDrawn 999 && mAppToken.startingData != null) { 1000 if (WindowManagerService.DEBUG_STARTING_WINDOW) Slog.v(WindowManagerService.TAG, "Finish starting " 1001 + mToken + ": first real window done animating"); 1002 mService.mFinishedStarting.add(mAppToken); 1003 mService.mH.sendEmptyMessage(H.FINISHED_STARTING); 1004 } 1005 1006 finishExit(); 1007 1008 if (mAppToken != null) { 1009 mAppToken.updateReportedVisibilityLocked(); 1010 } 1011 1012 return false; 1013 } 1014 finishExit()1015 void finishExit() { 1016 if (WindowManagerService.DEBUG_ANIM) Slog.v( 1017 WindowManagerService.TAG, "finishExit in " + this 1018 + ": exiting=" + mExiting 1019 + " remove=" + mRemoveOnExit 1020 + " windowAnimating=" + isWindowAnimating()); 1021 1022 final int N = mChildWindows.size(); 1023 for (int i=0; i<N; i++) { 1024 mChildWindows.get(i).finishExit(); 1025 } 1026 1027 if (!mExiting) { 1028 return; 1029 } 1030 1031 if (isWindowAnimating()) { 1032 return; 1033 } 1034 1035 if (WindowManagerService.localLOGV) Slog.v( 1036 WindowManagerService.TAG, "Exit animation finished in " + this 1037 + ": remove=" + mRemoveOnExit); 1038 if (mSurface != null) { 1039 mService.mDestroySurface.add(this); 1040 mDestroying = true; 1041 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(this, "HIDE (finishExit)", null); 1042 mSurfaceShown = false; 1043 try { 1044 mSurface.hide(); 1045 } catch (RuntimeException e) { 1046 Slog.w(WindowManagerService.TAG, "Error hiding surface in " + this, e); 1047 } 1048 mLastHidden = true; 1049 } 1050 mExiting = false; 1051 if (mRemoveOnExit) { 1052 mService.mPendingRemove.add(this); 1053 mRemoveOnExit = false; 1054 } 1055 } 1056 isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy)1057 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { 1058 if (dsdx < .99999f || dsdx > 1.00001f) return false; 1059 if (dtdy < .99999f || dtdy > 1.00001f) return false; 1060 if (dtdx < -.000001f || dtdx > .000001f) return false; 1061 if (dsdy < -.000001f || dsdy > .000001f) return false; 1062 return true; 1063 } 1064 prelayout()1065 void prelayout() { 1066 if (mEnforceSizeCompat) { 1067 mGlobalScale = mService.mCompatibleScreenScale; 1068 mInvGlobalScale = 1/mGlobalScale; 1069 } else { 1070 mGlobalScale = mInvGlobalScale = 1; 1071 } 1072 } 1073 computeShownFrameLocked()1074 void computeShownFrameLocked() { 1075 final boolean selfTransformation = mHasLocalTransformation; 1076 Transformation attachedTransformation = 1077 (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation) 1078 ? mAttachedWindow.mTransformation : null; 1079 Transformation appTransformation = 1080 (mAppToken != null && mAppToken.hasTransformation) 1081 ? mAppToken.transformation : null; 1082 1083 // Wallpapers are animated based on the "real" window they 1084 // are currently targeting. 1085 if (mAttrs.type == TYPE_WALLPAPER && mService.mLowerWallpaperTarget == null 1086 && mService.mWallpaperTarget != null) { 1087 if (mService.mWallpaperTarget.mHasLocalTransformation && 1088 mService.mWallpaperTarget.mAnimation != null && 1089 !mService.mWallpaperTarget.mAnimation.getDetachWallpaper()) { 1090 attachedTransformation = mService.mWallpaperTarget.mTransformation; 1091 if (WindowManagerService.DEBUG_WALLPAPER && attachedTransformation != null) { 1092 Slog.v(WindowManagerService.TAG, "WP target attached xform: " + attachedTransformation); 1093 } 1094 } 1095 if (mService.mWallpaperTarget.mAppToken != null && 1096 mService.mWallpaperTarget.mAppToken.hasTransformation && 1097 mService.mWallpaperTarget.mAppToken.animation != null && 1098 !mService.mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) { 1099 appTransformation = mService.mWallpaperTarget.mAppToken.transformation; 1100 if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) { 1101 Slog.v(WindowManagerService.TAG, "WP target app xform: " + appTransformation); 1102 } 1103 } 1104 } 1105 1106 final boolean screenAnimation = mService.mScreenRotationAnimation != null 1107 && mService.mScreenRotationAnimation.isAnimating(); 1108 if (selfTransformation || attachedTransformation != null 1109 || appTransformation != null || screenAnimation) { 1110 // cache often used attributes locally 1111 final Rect frame = mFrame; 1112 final float tmpFloats[] = mService.mTmpFloats; 1113 final Matrix tmpMatrix = mTmpMatrix; 1114 1115 // Compute the desired transformation. 1116 if (screenAnimation) { 1117 // If we are doing a screen animation, the global rotation 1118 // applied to windows can result in windows that are carefully 1119 // aligned with each other to slightly separate, allowing you 1120 // to see what is behind them. An unsightly mess. This... 1121 // thing... magically makes it call good: scale each window 1122 // slightly (two pixels larger in each dimension, from the 1123 // window's center). 1124 final float w = frame.width(); 1125 final float h = frame.height(); 1126 if (w>=1 && h>=1) { 1127 tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2); 1128 } else { 1129 tmpMatrix.reset(); 1130 } 1131 } else { 1132 tmpMatrix.reset(); 1133 } 1134 tmpMatrix.postScale(mGlobalScale, mGlobalScale); 1135 if (selfTransformation) { 1136 tmpMatrix.postConcat(mTransformation.getMatrix()); 1137 } 1138 tmpMatrix.postTranslate(frame.left + mXOffset, frame.top + mYOffset); 1139 if (attachedTransformation != null) { 1140 tmpMatrix.postConcat(attachedTransformation.getMatrix()); 1141 } 1142 if (appTransformation != null) { 1143 tmpMatrix.postConcat(appTransformation.getMatrix()); 1144 } 1145 if (screenAnimation) { 1146 tmpMatrix.postConcat( 1147 mService.mScreenRotationAnimation.getEnterTransformation().getMatrix()); 1148 } 1149 1150 // "convert" it into SurfaceFlinger's format 1151 // (a 2x2 matrix + an offset) 1152 // Here we must not transform the position of the surface 1153 // since it is already included in the transformation. 1154 //Slog.i(TAG, "Transform: " + matrix); 1155 1156 mHaveMatrix = true; 1157 tmpMatrix.getValues(tmpFloats); 1158 mDsDx = tmpFloats[Matrix.MSCALE_X]; 1159 mDtDx = tmpFloats[Matrix.MSKEW_Y]; 1160 mDsDy = tmpFloats[Matrix.MSKEW_X]; 1161 mDtDy = tmpFloats[Matrix.MSCALE_Y]; 1162 float x = tmpFloats[Matrix.MTRANS_X]; 1163 float y = tmpFloats[Matrix.MTRANS_Y]; 1164 int w = frame.width(); 1165 int h = frame.height(); 1166 mShownFrame.set(x, y, x+w, y+h); 1167 1168 // Now set the alpha... but because our current hardware 1169 // can't do alpha transformation on a non-opaque surface, 1170 // turn it off if we are running an animation that is also 1171 // transforming since it is more important to have that 1172 // animation be smooth. 1173 mShownAlpha = mAlpha; 1174 if (!mService.mLimitedAlphaCompositing 1175 || (!PixelFormat.formatHasAlpha(mAttrs.format) 1176 || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy) 1177 && x == frame.left && y == frame.top))) { 1178 //Slog.i(TAG, "Applying alpha transform"); 1179 if (selfTransformation) { 1180 mShownAlpha *= mTransformation.getAlpha(); 1181 } 1182 if (attachedTransformation != null) { 1183 mShownAlpha *= attachedTransformation.getAlpha(); 1184 } 1185 if (appTransformation != null) { 1186 mShownAlpha *= appTransformation.getAlpha(); 1187 } 1188 if (screenAnimation) { 1189 mShownAlpha *= 1190 mService.mScreenRotationAnimation.getEnterTransformation().getAlpha(); 1191 } 1192 } else { 1193 //Slog.i(TAG, "Not applying alpha transform"); 1194 } 1195 1196 if (WindowManagerService.localLOGV) Slog.v( 1197 WindowManagerService.TAG, "Continuing animation in " + this + 1198 ": " + mShownFrame + 1199 ", alpha=" + mTransformation.getAlpha()); 1200 return; 1201 } 1202 1203 mShownFrame.set(mFrame); 1204 if (mXOffset != 0 || mYOffset != 0) { 1205 mShownFrame.offset(mXOffset, mYOffset); 1206 } 1207 mShownAlpha = mAlpha; 1208 mHaveMatrix = false; 1209 mDsDx = mGlobalScale; 1210 mDtDx = 0; 1211 mDsDy = 0; 1212 mDtDy = mGlobalScale; 1213 } 1214 1215 /** 1216 * Is this window visible? It is not visible if there is no 1217 * surface, or we are in the process of running an exit animation 1218 * that will remove the surface, or its app token has been hidden. 1219 */ isVisibleLw()1220 public boolean isVisibleLw() { 1221 final AppWindowToken atoken = mAppToken; 1222 return mSurface != null && mPolicyVisibility && !mAttachedHidden 1223 && (atoken == null || !atoken.hiddenRequested) 1224 && !mExiting && !mDestroying; 1225 } 1226 1227 /** 1228 * Like {@link #isVisibleLw}, but also counts a window that is currently 1229 * "hidden" behind the keyguard as visible. This allows us to apply 1230 * things like window flags that impact the keyguard. 1231 * XXX I am starting to think we need to have ANOTHER visibility flag 1232 * for this "hidden behind keyguard" state rather than overloading 1233 * mPolicyVisibility. Ungh. 1234 */ isVisibleOrBehindKeyguardLw()1235 public boolean isVisibleOrBehindKeyguardLw() { 1236 if (mRootToken.waitingToShow && 1237 mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 1238 return false; 1239 } 1240 final AppWindowToken atoken = mAppToken; 1241 final boolean animating = atoken != null 1242 ? (atoken.animation != null) : false; 1243 return mSurface != null && !mDestroying && !mExiting 1244 && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested) 1245 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE 1246 && !mRootToken.hidden) 1247 || mAnimation != null || animating); 1248 } 1249 1250 /** 1251 * Is this window visible, ignoring its app token? It is not visible 1252 * if there is no surface, or we are in the process of running an exit animation 1253 * that will remove the surface. 1254 */ isWinVisibleLw()1255 public boolean isWinVisibleLw() { 1256 final AppWindowToken atoken = mAppToken; 1257 return mSurface != null && mPolicyVisibility && !mAttachedHidden 1258 && (atoken == null || !atoken.hiddenRequested || atoken.animating) 1259 && !mExiting && !mDestroying; 1260 } 1261 1262 /** 1263 * The same as isVisible(), but follows the current hidden state of 1264 * the associated app token, not the pending requested hidden state. 1265 */ isVisibleNow()1266 boolean isVisibleNow() { 1267 return mSurface != null && mPolicyVisibility && !mAttachedHidden 1268 && !mRootToken.hidden && !mExiting && !mDestroying; 1269 } 1270 1271 /** 1272 * Can this window possibly be a drag/drop target? The test here is 1273 * a combination of the above "visible now" with the check that the 1274 * Input Manager uses when discarding windows from input consideration. 1275 */ isPotentialDragTarget()1276 boolean isPotentialDragTarget() { 1277 return isVisibleNow() && !mRemoved 1278 && mInputChannel != null && mInputWindowHandle != null; 1279 } 1280 1281 /** 1282 * Same as isVisible(), but we also count it as visible between the 1283 * call to IWindowSession.add() and the first relayout(). 1284 */ isVisibleOrAdding()1285 boolean isVisibleOrAdding() { 1286 final AppWindowToken atoken = mAppToken; 1287 return ((mSurface != null && !mReportDestroySurface) 1288 || (!mRelayoutCalled && mViewVisibility == View.VISIBLE)) 1289 && mPolicyVisibility && !mAttachedHidden 1290 && (atoken == null || !atoken.hiddenRequested) 1291 && !mExiting && !mDestroying; 1292 } 1293 1294 /** 1295 * Is this window currently on-screen? It is on-screen either if it 1296 * is visible or it is currently running an animation before no longer 1297 * being visible. 1298 */ isOnScreen()1299 boolean isOnScreen() { 1300 final AppWindowToken atoken = mAppToken; 1301 if (atoken != null) { 1302 return mSurface != null && mPolicyVisibility && !mDestroying 1303 && ((!mAttachedHidden && !atoken.hiddenRequested) 1304 || mAnimation != null || atoken.animation != null); 1305 } else { 1306 return mSurface != null && mPolicyVisibility && !mDestroying 1307 && (!mAttachedHidden || mAnimation != null); 1308 } 1309 } 1310 1311 /** 1312 * Like isOnScreen(), but we don't return true if the window is part 1313 * of a transition that has not yet been started. 1314 */ isReadyForDisplay()1315 boolean isReadyForDisplay() { 1316 if (mRootToken.waitingToShow && 1317 mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 1318 return false; 1319 } 1320 final AppWindowToken atoken = mAppToken; 1321 final boolean animating = atoken != null 1322 ? (atoken.animation != null) : false; 1323 return mSurface != null && mPolicyVisibility && !mDestroying 1324 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE 1325 && !mRootToken.hidden) 1326 || mAnimation != null || animating); 1327 } 1328 1329 /** Is the window or its container currently animating? */ isAnimating()1330 boolean isAnimating() { 1331 final WindowState attached = mAttachedWindow; 1332 final AppWindowToken atoken = mAppToken; 1333 return mAnimation != null 1334 || (attached != null && attached.mAnimation != null) 1335 || (atoken != null && 1336 (atoken.animation != null 1337 || atoken.inPendingTransaction)); 1338 } 1339 1340 /** Is this window currently animating? */ isWindowAnimating()1341 boolean isWindowAnimating() { 1342 return mAnimation != null; 1343 } 1344 1345 /** 1346 * Like isOnScreen, but returns false if the surface hasn't yet 1347 * been drawn. 1348 */ isDisplayedLw()1349 public boolean isDisplayedLw() { 1350 final AppWindowToken atoken = mAppToken; 1351 return mSurface != null && mPolicyVisibility && !mDestroying 1352 && !mDrawPending && !mCommitDrawPending 1353 && ((!mAttachedHidden && 1354 (atoken == null || !atoken.hiddenRequested)) 1355 || mAnimating); 1356 } 1357 1358 /** 1359 * Returns true if the window has a surface that it has drawn a 1360 * complete UI in to. 1361 */ isDrawnLw()1362 public boolean isDrawnLw() { 1363 final AppWindowToken atoken = mAppToken; 1364 return mSurface != null && !mDestroying 1365 && !mDrawPending && !mCommitDrawPending; 1366 } 1367 1368 /** 1369 * Return true if the window is opaque and fully drawn. This indicates 1370 * it may obscure windows behind it. 1371 */ isOpaqueDrawn()1372 boolean isOpaqueDrawn() { 1373 return (mAttrs.format == PixelFormat.OPAQUE 1374 || mAttrs.type == TYPE_WALLPAPER) 1375 && mSurface != null && mAnimation == null 1376 && (mAppToken == null || mAppToken.animation == null) 1377 && !mDrawPending && !mCommitDrawPending; 1378 } 1379 1380 /** 1381 * Return whether this window is wanting to have a translation 1382 * animation applied to it for an in-progress move. (Only makes 1383 * sense to call from performLayoutAndPlaceSurfacesLockedInner().) 1384 */ shouldAnimateMove()1385 boolean shouldAnimateMove() { 1386 return mContentChanged && !mExiting && !mLastHidden && !mService.mDisplayFrozen 1387 && (mFrame.top != mLastFrame.top 1388 || mFrame.left != mLastFrame.left) 1389 && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove()) 1390 && mService.mPolicy.isScreenOnFully(); 1391 } 1392 isFullscreen(int screenWidth, int screenHeight)1393 boolean isFullscreen(int screenWidth, int screenHeight) { 1394 return mFrame.left <= 0 && mFrame.top <= 0 && 1395 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight; 1396 } 1397 removeLocked()1398 void removeLocked() { 1399 disposeInputChannel(); 1400 1401 if (mAttachedWindow != null) { 1402 if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Removing " + this + " from " + mAttachedWindow); 1403 mAttachedWindow.mChildWindows.remove(this); 1404 } 1405 destroySurfaceLocked(); 1406 mSession.windowRemovedLocked(); 1407 try { 1408 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0); 1409 } catch (RuntimeException e) { 1410 // Ignore if it has already been removed (usually because 1411 // we are doing this as part of processing a death note.) 1412 } 1413 } 1414 setInputChannel(InputChannel inputChannel)1415 void setInputChannel(InputChannel inputChannel) { 1416 if (mInputChannel != null) { 1417 throw new IllegalStateException("Window already has an input channel."); 1418 } 1419 1420 mInputChannel = inputChannel; 1421 mInputWindowHandle.inputChannel = inputChannel; 1422 } 1423 disposeInputChannel()1424 void disposeInputChannel() { 1425 if (mInputChannel != null) { 1426 mService.mInputManager.unregisterInputChannel(mInputChannel); 1427 1428 mInputChannel.dispose(); 1429 mInputChannel = null; 1430 } 1431 1432 mInputWindowHandle.inputChannel = null; 1433 } 1434 1435 private class DeathRecipient implements IBinder.DeathRecipient { binderDied()1436 public void binderDied() { 1437 try { 1438 synchronized(mService.mWindowMap) { 1439 WindowState win = mService.windowForClientLocked(mSession, mClient, false); 1440 Slog.i(WindowManagerService.TAG, "WIN DEATH: " + win); 1441 if (win != null) { 1442 mService.removeWindowLocked(mSession, win); 1443 } 1444 } 1445 } catch (IllegalArgumentException ex) { 1446 // This will happen if the window has already been 1447 // removed. 1448 } 1449 } 1450 } 1451 1452 /** Returns true if this window desires key events. */ canReceiveKeys()1453 public final boolean canReceiveKeys() { 1454 return isVisibleOrAdding() 1455 && (mViewVisibility == View.VISIBLE) 1456 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0); 1457 } 1458 hasDrawnLw()1459 public boolean hasDrawnLw() { 1460 return mHasDrawn; 1461 } 1462 showLw(boolean doAnimation)1463 public boolean showLw(boolean doAnimation) { 1464 return showLw(doAnimation, true); 1465 } 1466 showLw(boolean doAnimation, boolean requestAnim)1467 boolean showLw(boolean doAnimation, boolean requestAnim) { 1468 if (mPolicyVisibility && mPolicyVisibilityAfterAnim) { 1469 return false; 1470 } 1471 if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility true: " + this); 1472 if (doAnimation) { 1473 if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "doAnimation: mPolicyVisibility=" 1474 + mPolicyVisibility + " mAnimation=" + mAnimation); 1475 if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOnFully()) { 1476 doAnimation = false; 1477 } else if (mPolicyVisibility && mAnimation == null) { 1478 // Check for the case where we are currently visible and 1479 // not animating; we do not want to do animation at such a 1480 // point to become visible when we already are. 1481 doAnimation = false; 1482 } 1483 } 1484 mPolicyVisibility = true; 1485 mPolicyVisibilityAfterAnim = true; 1486 if (doAnimation) { 1487 mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true); 1488 } 1489 if (requestAnim) { 1490 mService.requestAnimationLocked(0); 1491 } 1492 return true; 1493 } 1494 hideLw(boolean doAnimation)1495 public boolean hideLw(boolean doAnimation) { 1496 return hideLw(doAnimation, true); 1497 } 1498 hideLw(boolean doAnimation, boolean requestAnim)1499 boolean hideLw(boolean doAnimation, boolean requestAnim) { 1500 if (doAnimation) { 1501 if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOnFully()) { 1502 doAnimation = false; 1503 } 1504 } 1505 boolean current = doAnimation ? mPolicyVisibilityAfterAnim 1506 : mPolicyVisibility; 1507 if (!current) { 1508 return false; 1509 } 1510 if (doAnimation) { 1511 mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false); 1512 if (mAnimation == null) { 1513 doAnimation = false; 1514 } 1515 } 1516 if (doAnimation) { 1517 mPolicyVisibilityAfterAnim = false; 1518 } else { 1519 if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility false: " + this); 1520 mPolicyVisibilityAfterAnim = false; 1521 mPolicyVisibility = false; 1522 // Window is no longer visible -- make sure if we were waiting 1523 // for it to be displayed before enabling the display, that 1524 // we allow the display to be enabled now. 1525 mService.enableScreenIfNeededLocked(); 1526 if (mService.mCurrentFocus == this) { 1527 mService.mFocusMayChange = true; 1528 } 1529 } 1530 if (requestAnim) { 1531 mService.requestAnimationLocked(0); 1532 } 1533 return true; 1534 } 1535 applyInsets(Region outRegion, Rect frame, Rect inset)1536 private static void applyInsets(Region outRegion, Rect frame, Rect inset) { 1537 outRegion.set( 1538 frame.left + inset.left, frame.top + inset.top, 1539 frame.right - inset.right, frame.bottom - inset.bottom); 1540 } 1541 getTouchableRegion(Region outRegion)1542 public void getTouchableRegion(Region outRegion) { 1543 final Rect frame = mFrame; 1544 switch (mTouchableInsets) { 1545 default: 1546 case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME: 1547 outRegion.set(frame); 1548 break; 1549 case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT: 1550 applyInsets(outRegion, frame, mGivenContentInsets); 1551 break; 1552 case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE: 1553 applyInsets(outRegion, frame, mGivenVisibleInsets); 1554 break; 1555 case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: { 1556 final Region givenTouchableRegion = mGivenTouchableRegion; 1557 outRegion.set(givenTouchableRegion); 1558 outRegion.translate(frame.left, frame.top); 1559 break; 1560 } 1561 } 1562 } 1563 dump(PrintWriter pw, String prefix, boolean dumpAll)1564 void dump(PrintWriter pw, String prefix, boolean dumpAll) { 1565 pw.print(prefix); pw.print("mSession="); pw.print(mSession); 1566 pw.print(" mClient="); pw.println(mClient.asBinder()); 1567 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs); 1568 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth); 1569 pw.print(" h="); pw.print(mRequestedHeight); 1570 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 1571 if (mAttachedWindow != null || mLayoutAttached) { 1572 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow); 1573 pw.print(" mLayoutAttached="); pw.println(mLayoutAttached); 1574 } 1575 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) { 1576 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow); 1577 pw.print(" mIsWallpaper="); pw.print(mIsWallpaper); 1578 pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer); 1579 pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible); 1580 } 1581 if (dumpAll) { 1582 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer); 1583 pw.print(" mSubLayer="); pw.print(mSubLayer); 1584 pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+"); 1585 pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment 1586 : (mAppToken != null ? mAppToken.animLayerAdjustment : 0))); 1587 pw.print("="); pw.print(mAnimLayer); 1588 pw.print(" mLastLayer="); pw.println(mLastLayer); 1589 } 1590 if (mSurface != null) { 1591 if (dumpAll) { 1592 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface); 1593 } 1594 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown); 1595 pw.print(" layer="); pw.print(mSurfaceLayer); 1596 pw.print(" alpha="); pw.print(mSurfaceAlpha); 1597 pw.print(" rect=("); pw.print(mSurfaceX); 1598 pw.print(","); pw.print(mSurfaceY); 1599 pw.print(") "); pw.print(mSurfaceW); 1600 pw.print(" x "); pw.println(mSurfaceH); 1601 } 1602 if (dumpAll) { 1603 pw.print(prefix); pw.print("mToken="); pw.println(mToken); 1604 pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken); 1605 if (mAppToken != null) { 1606 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken); 1607 } 1608 if (mTargetAppToken != null) { 1609 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken); 1610 } 1611 pw.print(prefix); pw.print("mViewVisibility=0x"); 1612 pw.print(Integer.toHexString(mViewVisibility)); 1613 pw.print(" mLastHidden="); pw.print(mLastHidden); 1614 pw.print(" mHaveFrame="); pw.print(mHaveFrame); 1615 pw.print(" mObscured="); pw.println(mObscured); 1616 pw.print(prefix); pw.print("mSeq="); pw.print(mSeq); 1617 pw.print(" mSystemUiVisibility=0x"); 1618 pw.println(Integer.toHexString(mSystemUiVisibility)); 1619 } 1620 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) { 1621 pw.print(prefix); pw.print("mPolicyVisibility="); 1622 pw.print(mPolicyVisibility); 1623 pw.print(" mPolicyVisibilityAfterAnim="); 1624 pw.print(mPolicyVisibilityAfterAnim); 1625 pw.print(" mAttachedHidden="); pw.println(mAttachedHidden); 1626 } 1627 if (!mRelayoutCalled) { 1628 pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled); 1629 } 1630 if (mXOffset != 0 || mYOffset != 0) { 1631 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset); 1632 pw.print(" y="); pw.println(mYOffset); 1633 } 1634 if (dumpAll) { 1635 pw.print(prefix); pw.print("mGivenContentInsets="); 1636 mGivenContentInsets.printShortString(pw); 1637 pw.print(" mGivenVisibleInsets="); 1638 mGivenVisibleInsets.printShortString(pw); 1639 pw.println(); 1640 if (mTouchableInsets != 0 || mGivenInsetsPending) { 1641 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets); 1642 pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending); 1643 } 1644 pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration); 1645 } 1646 pw.print(prefix); pw.print("mShownFrame="); 1647 mShownFrame.printShortString(pw); pw.println(); 1648 if (dumpAll) { 1649 pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw); 1650 pw.print(" last="); mLastFrame.printShortString(pw); 1651 pw.println(); 1652 } 1653 if (mEnforceSizeCompat) { 1654 pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw); 1655 pw.println(); 1656 } 1657 if (dumpAll) { 1658 pw.print(prefix); pw.print("mContainingFrame="); 1659 mContainingFrame.printShortString(pw); 1660 pw.print(" mParentFrame="); 1661 mParentFrame.printShortString(pw); 1662 pw.print(" mDisplayFrame="); 1663 mDisplayFrame.printShortString(pw); 1664 pw.println(); 1665 pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw); 1666 pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw); 1667 pw.println(); 1668 pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw); 1669 pw.print(" last="); mLastContentInsets.printShortString(pw); 1670 pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw); 1671 pw.print(" last="); mLastVisibleInsets.printShortString(pw); 1672 pw.println(); 1673 } 1674 if (mAnimating || mLocalAnimating || mAnimationIsEntrance 1675 || mAnimation != null) { 1676 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating); 1677 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating); 1678 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance); 1679 pw.print(" mAnimation="); pw.println(mAnimation); 1680 } 1681 if (mHasTransformation || mHasLocalTransformation) { 1682 pw.print(prefix); pw.print("XForm: has="); 1683 pw.print(mHasTransformation); 1684 pw.print(" hasLocal="); pw.print(mHasLocalTransformation); 1685 pw.print(" "); mTransformation.printShortString(pw); 1686 pw.println(); 1687 } 1688 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) { 1689 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha); 1690 pw.print(" mAlpha="); pw.print(mAlpha); 1691 pw.print(" mLastAlpha="); pw.println(mLastAlpha); 1692 } 1693 if (mHaveMatrix || mGlobalScale != 1) { 1694 pw.print(prefix); pw.print("mGlobalScale="); pw.print(mGlobalScale); 1695 pw.print(" mDsDx="); pw.print(mDsDx); 1696 pw.print(" mDtDx="); pw.print(mDtDx); 1697 pw.print(" mDsDy="); pw.print(mDsDy); 1698 pw.print(" mDtDy="); pw.println(mDtDy); 1699 } 1700 if (dumpAll) { 1701 pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending); 1702 pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending); 1703 pw.print(" mReadyToShow="); pw.print(mReadyToShow); 1704 pw.print(" mHasDrawn="); pw.println(mHasDrawn); 1705 } 1706 if (mExiting || mRemoveOnExit || mDestroying || mRemoved) { 1707 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting); 1708 pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit); 1709 pw.print(" mDestroying="); pw.print(mDestroying); 1710 pw.print(" mRemoved="); pw.println(mRemoved); 1711 } 1712 if (mOrientationChanging || mAppFreezing || mTurnOnScreen) { 1713 pw.print(prefix); pw.print("mOrientationChanging="); 1714 pw.print(mOrientationChanging); 1715 pw.print(" mAppFreezing="); pw.print(mAppFreezing); 1716 pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen); 1717 } 1718 if (mHScale != 1 || mVScale != 1) { 1719 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale); 1720 pw.print(" mVScale="); pw.println(mVScale); 1721 } 1722 if (mWallpaperX != -1 || mWallpaperY != -1) { 1723 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX); 1724 pw.print(" mWallpaperY="); pw.println(mWallpaperY); 1725 } 1726 if (mWallpaperXStep != -1 || mWallpaperYStep != -1) { 1727 pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep); 1728 pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep); 1729 } 1730 } 1731 makeInputChannelName()1732 String makeInputChannelName() { 1733 return Integer.toHexString(System.identityHashCode(this)) 1734 + " " + mAttrs.getTitle(); 1735 } 1736 1737 @Override toString()1738 public String toString() { 1739 if (mStringNameCache == null || mLastTitle != mAttrs.getTitle() 1740 || mWasPaused != mToken.paused) { 1741 mLastTitle = mAttrs.getTitle(); 1742 mWasPaused = mToken.paused; 1743 mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this)) 1744 + " " + mLastTitle + " paused=" + mWasPaused + "}"; 1745 } 1746 return mStringNameCache; 1747 } 1748 }