WindowState.java revision 5962b12bedc4a1d0354816c1cd6b06ba04f6d807
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.FIRST_SUB_WINDOW; 20import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW; 21import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; 22import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 23import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 24import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 25 26import com.android.server.input.InputWindowHandle; 27 28import android.content.Context; 29import android.content.res.Configuration; 30import android.graphics.Matrix; 31import android.graphics.PixelFormat; 32import android.graphics.Rect; 33import android.graphics.RectF; 34import android.graphics.Region; 35import android.os.IBinder; 36import android.os.RemoteException; 37import android.os.UserHandle; 38import android.util.Slog; 39import android.view.DisplayInfo; 40import android.view.Gravity; 41import android.view.IApplicationToken; 42import android.view.IWindow; 43import android.view.InputChannel; 44import android.view.View; 45import android.view.ViewTreeObserver; 46import android.view.WindowManager; 47import android.view.WindowManagerPolicy; 48 49import java.io.PrintWriter; 50import java.util.ArrayList; 51 52class WindowList extends ArrayList<WindowState> { 53} 54 55/** 56 * A window in the window manager. 57 */ 58final class WindowState implements WindowManagerPolicy.WindowState { 59 static final String TAG = "WindowState"; 60 61 static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY; 62 static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS; 63 static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS; 64 static final boolean SHOW_SURFACE_ALLOC = WindowManagerService.SHOW_SURFACE_ALLOC; 65 66 final WindowManagerService mService; 67 final WindowManagerPolicy mPolicy; 68 final Context mContext; 69 final Session mSession; 70 final IWindow mClient; 71 WindowToken mToken; 72 WindowToken mRootToken; 73 AppWindowToken mAppToken; 74 AppWindowToken mTargetAppToken; 75 76 // mAttrs.flags is tested in animation without being locked. If the bits tested are ever 77 // modified they will need to be locked. 78 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams(); 79 final DeathRecipient mDeathRecipient; 80 final WindowState mAttachedWindow; 81 final ArrayList<WindowState> mChildWindows = new ArrayList<WindowState>(); 82 final int mBaseLayer; 83 final int mSubLayer; 84 final boolean mLayoutAttached; 85 final boolean mIsImWindow; 86 final boolean mIsWallpaper; 87 final boolean mIsFloatingLayer; 88 int mSeq; 89 boolean mEnforceSizeCompat; 90 int mViewVisibility; 91 int mSystemUiVisibility; 92 boolean mPolicyVisibility = true; 93 boolean mPolicyVisibilityAfterAnim = true; 94 boolean mAppFreezing; 95 boolean mAttachedHidden; // is our parent window hidden? 96 boolean mWallpaperVisible; // for wallpaper, what was last vis report? 97 98 /** 99 * The window size that was requested by the application. These are in 100 * the application's coordinate space (without compatibility scale applied). 101 */ 102 int mRequestedWidth; 103 int mRequestedHeight; 104 int mLastRequestedWidth; 105 int mLastRequestedHeight; 106 107 int mLayer; 108 boolean mHaveFrame; 109 boolean mObscured; 110 boolean mTurnOnScreen; 111 112 int mLayoutSeq = -1; 113 114 Configuration mConfiguration = null; 115 116 /** 117 * Actual frame shown on-screen (may be modified by animation). These 118 * are in the screen's coordinate space (WITH the compatibility scale 119 * applied). 120 */ 121 final RectF mShownFrame = new RectF(); 122 123 /** 124 * Insets that determine the actually visible area. These are in the application's 125 * coordinate space (without compatibility scale applied). 126 */ 127 final Rect mVisibleInsets = new Rect(); 128 final Rect mLastVisibleInsets = new Rect(); 129 boolean mVisibleInsetsChanged; 130 131 /** 132 * Insets that are covered by system windows (such as the status bar) and 133 * transient docking windows (such as the IME). These are in the application's 134 * coordinate space (without compatibility scale applied). 135 */ 136 final Rect mContentInsets = new Rect(); 137 final Rect mLastContentInsets = new Rect(); 138 boolean mContentInsetsChanged; 139 140 /** 141 * Set to true if we are waiting for this window to receive its 142 * given internal insets before laying out other windows based on it. 143 */ 144 boolean mGivenInsetsPending; 145 146 /** 147 * These are the content insets that were given during layout for 148 * this window, to be applied to windows behind it. 149 */ 150 final Rect mGivenContentInsets = new Rect(); 151 152 /** 153 * These are the visible insets that were given during layout for 154 * this window, to be applied to windows behind it. 155 */ 156 final Rect mGivenVisibleInsets = new Rect(); 157 158 /** 159 * This is the given touchable area relative to the window frame, or null if none. 160 */ 161 final Region mGivenTouchableRegion = new Region(); 162 163 /** 164 * Flag indicating whether the touchable region should be adjusted by 165 * the visible insets; if false the area outside the visible insets is 166 * NOT touchable, so we must use those to adjust the frame during hit 167 * tests. 168 */ 169 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; 170 171 /** 172 * This is rectangle of the window's surface that is not covered by 173 * system decorations. 174 */ 175 final Rect mSystemDecorRect = new Rect(); 176 final Rect mLastSystemDecorRect = new Rect(); 177 178 // Current transformation being applied. 179 float mGlobalScale=1; 180 float mInvGlobalScale=1; 181 float mHScale=1, mVScale=1; 182 float mLastHScale=1, mLastVScale=1; 183 final Matrix mTmpMatrix = new Matrix(); 184 185 // "Real" frame that the application sees, in display coordinate space. 186 final Rect mFrame = new Rect(); 187 final Rect mLastFrame = new Rect(); 188 // Frame that is scaled to the application's coordinate space when in 189 // screen size compatibility mode. 190 final Rect mCompatFrame = new Rect(); 191 192 final Rect mContainingFrame = new Rect(); 193 final Rect mDisplayFrame = new Rect(); 194 final Rect mContentFrame = new Rect(); 195 final Rect mParentFrame = new Rect(); 196 final Rect mVisibleFrame = new Rect(); 197 198 boolean mContentChanged; 199 200 // If a window showing a wallpaper: the requested offset for the 201 // wallpaper; if a wallpaper window: the currently applied offset. 202 float mWallpaperX = -1; 203 float mWallpaperY = -1; 204 205 // If a window showing a wallpaper: what fraction of the offset 206 // range corresponds to a full virtual screen. 207 float mWallpaperXStep = -1; 208 float mWallpaperYStep = -1; 209 210 // Wallpaper windows: pixels offset based on above variables. 211 int mXOffset; 212 int mYOffset; 213 214 // This is set after IWindowSession.relayout() has been called at 215 // least once for the window. It allows us to detect the situation 216 // where we don't yet have a surface, but should have one soon, so 217 // we can give the window focus before waiting for the relayout. 218 boolean mRelayoutCalled; 219 220 // If the application has called relayout() with changes that can 221 // impact its window's size, we need to perform a layout pass on it 222 // even if it is not currently visible for layout. This is set 223 // when in that case until the layout is done. 224 boolean mLayoutNeeded; 225 226 // Currently running an exit animation? 227 boolean mExiting; 228 229 // Currently on the mDestroySurface list? 230 boolean mDestroying; 231 232 // Completely remove from window manager after exit animation? 233 boolean mRemoveOnExit; 234 235 // Set when the orientation is changing and this window has not yet 236 // been updated for the new orientation. 237 boolean mOrientationChanging; 238 239 // Is this window now (or just being) removed? 240 boolean mRemoved; 241 242 // Temp for keeping track of windows that have been removed when 243 // rebuilding window list. 244 boolean mRebuilding; 245 246 // Input channel and input window handle used by the input dispatcher. 247 final InputWindowHandle mInputWindowHandle; 248 InputChannel mInputChannel; 249 250 // Used to improve performance of toString() 251 String mStringNameCache; 252 CharSequence mLastTitle; 253 boolean mWasPaused; 254 255 final WindowStateAnimator mWinAnimator; 256 257 boolean mHasSurface = false; 258 259 DisplayContent mDisplayContent; 260 261 // UserId and appId of the owner. Don't display windows of non-current user. 262 int mOwnerUid; 263 264 /** When true this window can be displayed on screens owther than mOwnerUid's */ 265 private boolean mShowToOwnerOnly; 266 267 WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, 268 WindowState attachedWindow, int seq, WindowManager.LayoutParams a, 269 int viewVisibility, final DisplayContent displayContent) { 270 mService = service; 271 mSession = s; 272 mClient = c; 273 mToken = token; 274 mOwnerUid = s.mUid; 275 mAttrs.copyFrom(a); 276 mViewVisibility = viewVisibility; 277 mDisplayContent = displayContent; 278 mPolicy = mService.mPolicy; 279 mContext = mService.mContext; 280 DeathRecipient deathRecipient = new DeathRecipient(); 281 mSeq = seq; 282 mEnforceSizeCompat = (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0; 283 if (WindowManagerService.localLOGV) Slog.v( 284 TAG, "Window " + this + " client=" + c.asBinder() 285 + " token=" + token + " (" + mAttrs.token + ")"); 286 try { 287 c.asBinder().linkToDeath(deathRecipient, 0); 288 } catch (RemoteException e) { 289 mDeathRecipient = null; 290 mAttachedWindow = null; 291 mLayoutAttached = false; 292 mIsImWindow = false; 293 mIsWallpaper = false; 294 mIsFloatingLayer = false; 295 mBaseLayer = 0; 296 mSubLayer = 0; 297 mInputWindowHandle = null; 298 mWinAnimator = null; 299 return; 300 } 301 mDeathRecipient = deathRecipient; 302 303 if ((mAttrs.type >= FIRST_SUB_WINDOW && 304 mAttrs.type <= LAST_SUB_WINDOW)) { 305 // The multiplier here is to reserve space for multiple 306 // windows in the same type layer. 307 mBaseLayer = mPolicy.windowTypeToLayerLw( 308 attachedWindow.mAttrs.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER 309 + WindowManagerService.TYPE_LAYER_OFFSET; 310 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type); 311 mAttachedWindow = attachedWindow; 312 if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow); 313 mAttachedWindow.mChildWindows.add(this); 314 mLayoutAttached = mAttrs.type != 315 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 316 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD 317 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG; 318 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER; 319 mIsFloatingLayer = mIsImWindow || mIsWallpaper; 320 } else { 321 // The multiplier here is to reserve space for multiple 322 // windows in the same type layer. 323 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type) 324 * WindowManagerService.TYPE_LAYER_MULTIPLIER 325 + WindowManagerService.TYPE_LAYER_OFFSET; 326 mSubLayer = 0; 327 mAttachedWindow = null; 328 mLayoutAttached = false; 329 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD 330 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG; 331 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER; 332 mIsFloatingLayer = mIsImWindow || mIsWallpaper; 333 } 334 335 WindowState appWin = this; 336 while (appWin.mAttachedWindow != null) { 337 appWin = appWin.mAttachedWindow; 338 } 339 WindowToken appToken = appWin.mToken; 340 while (appToken.appWindowToken == null) { 341 WindowToken parent = mService.mTokenMap.get(appToken.token); 342 if (parent == null || appToken == parent) { 343 break; 344 } 345 appToken = parent; 346 } 347 mRootToken = appToken; 348 mAppToken = appToken.appWindowToken; 349 350 mWinAnimator = new WindowStateAnimator(this); 351 mWinAnimator.mAlpha = a.alpha; 352 353 mRequestedWidth = 0; 354 mRequestedHeight = 0; 355 mLastRequestedWidth = 0; 356 mLastRequestedHeight = 0; 357 mXOffset = 0; 358 mYOffset = 0; 359 mLayer = 0; 360 mInputWindowHandle = new InputWindowHandle( 361 mAppToken != null ? mAppToken.mInputApplicationHandle : null, this, 362 displayContent.getDisplayId()); 363 } 364 365 void attach() { 366 if (WindowManagerService.localLOGV) Slog.v( 367 TAG, "Attaching " + this + " token=" + mToken 368 + ", list=" + mToken.windows); 369 mSession.windowAddedLocked(); 370 } 371 372 @Override 373 public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) { 374 mHaveFrame = true; 375 376 final Rect container = mContainingFrame; 377 container.set(pf); 378 379 final Rect display = mDisplayFrame; 380 display.set(df); 381 382 final int pw = container.right - container.left; 383 final int ph = container.bottom - container.top; 384 385 int w,h; 386 if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0) { 387 if (mAttrs.width < 0) { 388 w = pw; 389 } else if (mEnforceSizeCompat) { 390 w = (int)(mAttrs.width * mGlobalScale + .5f); 391 } else { 392 w = mAttrs.width; 393 } 394 if (mAttrs.height < 0) { 395 h = ph; 396 } else if (mEnforceSizeCompat) { 397 h = (int)(mAttrs.height * mGlobalScale + .5f); 398 } else { 399 h = mAttrs.height; 400 } 401 } else { 402 if (mAttrs.width == WindowManager.LayoutParams.MATCH_PARENT) { 403 w = pw; 404 } else if (mEnforceSizeCompat) { 405 w = (int)(mRequestedWidth * mGlobalScale + .5f); 406 } else { 407 w = mRequestedWidth; 408 } 409 if (mAttrs.height == WindowManager.LayoutParams.MATCH_PARENT) { 410 h = ph; 411 } else if (mEnforceSizeCompat) { 412 h = (int)(mRequestedHeight * mGlobalScale + .5f); 413 } else { 414 h = mRequestedHeight; 415 } 416 } 417 418 if (!mParentFrame.equals(pf)) { 419 //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame 420 // + " to " + pf); 421 mParentFrame.set(pf); 422 mContentChanged = true; 423 } 424 if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) { 425 mLastRequestedWidth = mRequestedWidth; 426 mLastRequestedHeight = mRequestedHeight; 427 mContentChanged = true; 428 } 429 430 final Rect content = mContentFrame; 431 content.set(cf); 432 433 final Rect visible = mVisibleFrame; 434 visible.set(vf); 435 436 final Rect frame = mFrame; 437 final int fw = frame.width(); 438 final int fh = frame.height(); 439 440 //System.out.println("In: w=" + w + " h=" + h + " container=" + 441 // container + " x=" + mAttrs.x + " y=" + mAttrs.y); 442 443 float x, y; 444 if (mEnforceSizeCompat) { 445 x = mAttrs.x * mGlobalScale; 446 y = mAttrs.y * mGlobalScale; 447 } else { 448 x = mAttrs.x; 449 y = mAttrs.y; 450 } 451 452 Gravity.apply(mAttrs.gravity, w, h, container, 453 (int) (x + mAttrs.horizontalMargin * pw), 454 (int) (y + mAttrs.verticalMargin * ph), frame); 455 456 //System.out.println("Out: " + mFrame); 457 458 // Now make sure the window fits in the overall display. 459 Gravity.applyDisplay(mAttrs.gravity, df, frame); 460 461 // Make sure the system, content and visible frames are inside of the 462 // final window frame. 463 if (content.left < frame.left) content.left = frame.left; 464 if (content.top < frame.top) content.top = frame.top; 465 if (content.right > frame.right) content.right = frame.right; 466 if (content.bottom > frame.bottom) content.bottom = frame.bottom; 467 if (visible.left < frame.left) visible.left = frame.left; 468 if (visible.top < frame.top) visible.top = frame.top; 469 if (visible.right > frame.right) visible.right = frame.right; 470 if (visible.bottom > frame.bottom) visible.bottom = frame.bottom; 471 472 final Rect contentInsets = mContentInsets; 473 contentInsets.left = content.left-frame.left; 474 contentInsets.top = content.top-frame.top; 475 contentInsets.right = frame.right-content.right; 476 contentInsets.bottom = frame.bottom-content.bottom; 477 478 final Rect visibleInsets = mVisibleInsets; 479 visibleInsets.left = visible.left-frame.left; 480 visibleInsets.top = visible.top-frame.top; 481 visibleInsets.right = frame.right-visible.right; 482 visibleInsets.bottom = frame.bottom-visible.bottom; 483 484 mCompatFrame.set(frame); 485 if (mEnforceSizeCompat) { 486 // If there is a size compatibility scale being applied to the 487 // window, we need to apply this to its insets so that they are 488 // reported to the app in its coordinate space. 489 contentInsets.scale(mInvGlobalScale); 490 visibleInsets.scale(mInvGlobalScale); 491 492 // Also the scaled frame that we report to the app needs to be 493 // adjusted to be in its coordinate space. 494 mCompatFrame.scale(mInvGlobalScale); 495 } 496 497 if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) { 498 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo(); 499 mService.updateWallpaperOffsetLocked(this, displayInfo.appWidth, displayInfo.appHeight, 500 false); 501 } 502 503 if (WindowManagerService.localLOGV) { 504 //if ("com.google.android.youtube".equals(mAttrs.packageName) 505 // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { 506 Slog.v(TAG, "Resolving (mRequestedWidth=" 507 + mRequestedWidth + ", mRequestedheight=" 508 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph 509 + "): frame=" + mFrame.toShortString() 510 + " ci=" + contentInsets.toShortString() 511 + " vi=" + visibleInsets.toShortString()); 512 //} 513 } 514 } 515 516 MagnificationSpec getWindowMagnificationSpecLocked() { 517 MagnificationSpec spec = mDisplayContent.mMagnificationSpec; 518 if (spec != null && !spec.isNop()) { 519 if (mAttachedWindow != null) { 520 if (!mPolicy.canMagnifyWindowLw(mAttachedWindow.mAttrs)) { 521 return null; 522 } 523 } 524 if (!mPolicy.canMagnifyWindowLw(mAttrs)) { 525 return null; 526 } 527 } 528 return spec; 529 } 530 531 @Override 532 public Rect getFrameLw() { 533 return mFrame; 534 } 535 536 @Override 537 public RectF getShownFrameLw() { 538 return mShownFrame; 539 } 540 541 @Override 542 public Rect getDisplayFrameLw() { 543 return mDisplayFrame; 544 } 545 546 @Override 547 public Rect getContentFrameLw() { 548 return mContentFrame; 549 } 550 551 @Override 552 public Rect getVisibleFrameLw() { 553 return mVisibleFrame; 554 } 555 556 @Override 557 public boolean getGivenInsetsPendingLw() { 558 return mGivenInsetsPending; 559 } 560 561 @Override 562 public Rect getGivenContentInsetsLw() { 563 return mGivenContentInsets; 564 } 565 566 @Override 567 public Rect getGivenVisibleInsetsLw() { 568 return mGivenVisibleInsets; 569 } 570 571 @Override 572 public WindowManager.LayoutParams getAttrs() { 573 return mAttrs; 574 } 575 576 @Override 577 public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) { 578 int index = -1; 579 WindowState ws = this; 580 WindowList windows = getWindowList(); 581 while (true) { 582 if ((ws.mAttrs.privateFlags 583 & WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY) != 0) { 584 return (ws.mAttrs.flags & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0; 585 } 586 // If we reached the bottom of the range of windows we are considering, 587 // assume no menu is needed. 588 if (ws == bottom) { 589 return false; 590 } 591 // The current window hasn't specified whether menu key is needed; 592 // look behind it. 593 // First, we may need to determine the starting position. 594 if (index < 0) { 595 index = windows.indexOf(ws); 596 } 597 index--; 598 if (index < 0) { 599 return false; 600 } 601 ws = windows.get(index); 602 } 603 } 604 605 @Override 606 public int getSystemUiVisibility() { 607 return mSystemUiVisibility; 608 } 609 610 @Override 611 public int getSurfaceLayer() { 612 return mLayer; 613 } 614 615 @Override 616 public IApplicationToken getAppToken() { 617 return mAppToken != null ? mAppToken.appToken : null; 618 } 619 620 public int getDisplayId() { 621 return mDisplayContent.getDisplayId(); 622 } 623 624 public long getInputDispatchingTimeoutNanos() { 625 return mAppToken != null 626 ? mAppToken.inputDispatchingTimeoutNanos 627 : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 628 } 629 630 public boolean hasAppShownWindows() { 631 return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed); 632 } 633 634 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { 635 if (dsdx < .99999f || dsdx > 1.00001f) return false; 636 if (dtdy < .99999f || dtdy > 1.00001f) return false; 637 if (dtdx < -.000001f || dtdx > .000001f) return false; 638 if (dsdy < -.000001f || dsdy > .000001f) return false; 639 return true; 640 } 641 642 void prelayout() { 643 if (mEnforceSizeCompat) { 644 mGlobalScale = mService.mCompatibleScreenScale; 645 mInvGlobalScale = 1/mGlobalScale; 646 } else { 647 mGlobalScale = mInvGlobalScale = 1; 648 } 649 } 650 651 /** 652 * Is this window visible? It is not visible if there is no 653 * surface, or we are in the process of running an exit animation 654 * that will remove the surface, or its app token has been hidden. 655 */ 656 @Override 657 public boolean isVisibleLw() { 658 final AppWindowToken atoken = mAppToken; 659 return mHasSurface && mPolicyVisibility && !mAttachedHidden 660 && (atoken == null || !atoken.hiddenRequested) 661 && !mExiting && !mDestroying; 662 } 663 664 /** 665 * Like {@link #isVisibleLw}, but also counts a window that is currently 666 * "hidden" behind the keyguard as visible. This allows us to apply 667 * things like window flags that impact the keyguard. 668 * XXX I am starting to think we need to have ANOTHER visibility flag 669 * for this "hidden behind keyguard" state rather than overloading 670 * mPolicyVisibility. Ungh. 671 */ 672 @Override 673 public boolean isVisibleOrBehindKeyguardLw() { 674 if (mRootToken.waitingToShow && 675 mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 676 return false; 677 } 678 final AppWindowToken atoken = mAppToken; 679 final boolean animating = atoken != null 680 ? (atoken.mAppAnimator.animation != null) : false; 681 return mHasSurface && !mDestroying && !mExiting 682 && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested) 683 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE 684 && !mRootToken.hidden) 685 || mWinAnimator.mAnimation != null || animating); 686 } 687 688 /** 689 * Is this window visible, ignoring its app token? It is not visible 690 * if there is no surface, or we are in the process of running an exit animation 691 * that will remove the surface. 692 */ 693 public boolean isWinVisibleLw() { 694 final AppWindowToken atoken = mAppToken; 695 return mHasSurface && mPolicyVisibility && !mAttachedHidden 696 && (atoken == null || !atoken.hiddenRequested || atoken.mAppAnimator.animating) 697 && !mExiting && !mDestroying; 698 } 699 700 /** 701 * The same as isVisible(), but follows the current hidden state of 702 * the associated app token, not the pending requested hidden state. 703 */ 704 boolean isVisibleNow() { 705 return mHasSurface && mPolicyVisibility && !mAttachedHidden 706 && !mRootToken.hidden && !mExiting && !mDestroying; 707 } 708 709 /** 710 * Can this window possibly be a drag/drop target? The test here is 711 * a combination of the above "visible now" with the check that the 712 * Input Manager uses when discarding windows from input consideration. 713 */ 714 boolean isPotentialDragTarget() { 715 return isVisibleNow() && !mRemoved 716 && mInputChannel != null && mInputWindowHandle != null; 717 } 718 719 /** 720 * Same as isVisible(), but we also count it as visible between the 721 * call to IWindowSession.add() and the first relayout(). 722 */ 723 boolean isVisibleOrAdding() { 724 final AppWindowToken atoken = mAppToken; 725 return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE)) 726 && mPolicyVisibility && !mAttachedHidden 727 && (atoken == null || !atoken.hiddenRequested) 728 && !mExiting && !mDestroying; 729 } 730 731 /** 732 * Is this window currently on-screen? It is on-screen either if it 733 * is visible or it is currently running an animation before no longer 734 * being visible. 735 */ 736 boolean isOnScreen() { 737 if (!mHasSurface || !mPolicyVisibility || mDestroying) { 738 return false; 739 } 740 final AppWindowToken atoken = mAppToken; 741 if (atoken != null) { 742 return ((!mAttachedHidden && !atoken.hiddenRequested) 743 || mWinAnimator.mAnimation != null || atoken.mAppAnimator.animation != null); 744 } 745 return !mAttachedHidden || mWinAnimator.mAnimation != null; 746 } 747 748 /** 749 * Like isOnScreen(), but we don't return true if the window is part 750 * of a transition that has not yet been started. 751 */ 752 boolean isReadyForDisplay() { 753 if (mRootToken.waitingToShow && 754 mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 755 return false; 756 } 757 return mHasSurface && mPolicyVisibility && !mDestroying 758 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE 759 && !mRootToken.hidden) 760 || mWinAnimator.mAnimation != null 761 || ((mAppToken != null) && (mAppToken.mAppAnimator.animation != null))); 762 } 763 764 /** 765 * Like isReadyForDisplay(), but ignores any force hiding of the window due 766 * to the keyguard. 767 */ 768 boolean isReadyForDisplayIgnoringKeyguard() { 769 if (mRootToken.waitingToShow && 770 mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 771 return false; 772 } 773 final AppWindowToken atoken = mAppToken; 774 if (atoken == null && !mPolicyVisibility) { 775 // If this is not an app window, and the policy has asked to force 776 // hide, then we really do want to hide. 777 return false; 778 } 779 return mHasSurface && !mDestroying 780 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE 781 && !mRootToken.hidden) 782 || mWinAnimator.mAnimation != null 783 || ((atoken != null) && (atoken.mAppAnimator.animation != null) 784 && !mWinAnimator.isDummyAnimation())); 785 } 786 787 /** 788 * Like isOnScreen, but returns false if the surface hasn't yet 789 * been drawn. 790 */ 791 public boolean isDisplayedLw() { 792 final AppWindowToken atoken = mAppToken; 793 return isDrawnLw() && mPolicyVisibility 794 && ((!mAttachedHidden && 795 (atoken == null || !atoken.hiddenRequested)) 796 || mWinAnimator.mAnimating); 797 } 798 799 /** 800 * Return true if this window (or a window it is attached to, but not 801 * considering its app token) is currently animating. 802 */ 803 public boolean isAnimatingLw() { 804 return mWinAnimator.mAnimation != null; 805 } 806 807 @Override 808 public boolean isGoneForLayoutLw() { 809 final AppWindowToken atoken = mAppToken; 810 return mViewVisibility == View.GONE 811 || !mRelayoutCalled 812 || (atoken == null && mRootToken.hidden) 813 || (atoken != null && (atoken.hiddenRequested || atoken.hidden)) 814 || mAttachedHidden 815 || mExiting || mDestroying; 816 } 817 818 /** 819 * Returns true if the window has a surface that it has drawn a 820 * complete UI in to. 821 */ 822 public boolean isDrawnLw() { 823 return mHasSurface && !mDestroying && 824 (mWinAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW 825 || mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN); 826 } 827 828 /** 829 * Return true if the window is opaque and fully drawn. This indicates 830 * it may obscure windows behind it. 831 */ 832 boolean isOpaqueDrawn() { 833 return (mAttrs.format == PixelFormat.OPAQUE 834 || mAttrs.type == TYPE_WALLPAPER) 835 && isDrawnLw() && mWinAnimator.mAnimation == null 836 && (mAppToken == null || mAppToken.mAppAnimator.animation == null); 837 } 838 839 /** 840 * Return whether this window is wanting to have a translation 841 * animation applied to it for an in-progress move. (Only makes 842 * sense to call from performLayoutAndPlaceSurfacesLockedInner().) 843 */ 844 boolean shouldAnimateMove() { 845 return mContentChanged && !mExiting && !mWinAnimator.mLastHidden && mService.okToDisplay() 846 && (mFrame.top != mLastFrame.top 847 || mFrame.left != mLastFrame.left) 848 && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove()); 849 } 850 851 boolean isFullscreen(int screenWidth, int screenHeight) { 852 return mFrame.left <= 0 && mFrame.top <= 0 && 853 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight; 854 } 855 856 boolean isConfigChanged() { 857 return mConfiguration != mService.mCurConfiguration 858 && (mConfiguration == null 859 || (mConfiguration.diff(mService.mCurConfiguration) != 0)); 860 } 861 862 boolean isConfigDiff(int mask) { 863 return mConfiguration != mService.mCurConfiguration 864 && mConfiguration != null 865 && (mConfiguration.diff(mService.mCurConfiguration) & mask) != 0; 866 } 867 868 void removeLocked() { 869 disposeInputChannel(); 870 871 if (mAttachedWindow != null) { 872 if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow); 873 mAttachedWindow.mChildWindows.remove(this); 874 } 875 mWinAnimator.destroyDeferredSurfaceLocked(); 876 mWinAnimator.destroySurfaceLocked(); 877 mSession.windowRemovedLocked(); 878 try { 879 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0); 880 } catch (RuntimeException e) { 881 // Ignore if it has already been removed (usually because 882 // we are doing this as part of processing a death note.) 883 } 884 } 885 886 void setInputChannel(InputChannel inputChannel) { 887 if (mInputChannel != null) { 888 throw new IllegalStateException("Window already has an input channel."); 889 } 890 891 mInputChannel = inputChannel; 892 mInputWindowHandle.inputChannel = inputChannel; 893 } 894 895 void disposeInputChannel() { 896 if (mInputChannel != null) { 897 mService.mInputManager.unregisterInputChannel(mInputChannel); 898 899 mInputChannel.dispose(); 900 mInputChannel = null; 901 } 902 903 mInputWindowHandle.inputChannel = null; 904 } 905 906 private class DeathRecipient implements IBinder.DeathRecipient { 907 public void binderDied() { 908 try { 909 synchronized(mService.mWindowMap) { 910 WindowState win = mService.windowForClientLocked(mSession, mClient, false); 911 Slog.i(TAG, "WIN DEATH: " + win); 912 if (win != null) { 913 mService.removeWindowLocked(mSession, win); 914 } 915 } 916 } catch (IllegalArgumentException ex) { 917 // This will happen if the window has already been 918 // removed. 919 } 920 } 921 } 922 923 /** Returns true if this window desires key events. 924 * TODO(cmautner): Is this the same as {@link WindowManagerService#canBeImeTarget} 925 */ 926 public final boolean canReceiveKeys() { 927 return isVisibleOrAdding() 928 && (mViewVisibility == View.VISIBLE) 929 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0); 930 } 931 932 @Override 933 public boolean hasDrawnLw() { 934 return mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN; 935 } 936 937 @Override 938 public boolean showLw(boolean doAnimation) { 939 return showLw(doAnimation, true); 940 } 941 942 boolean showLw(boolean doAnimation, boolean requestAnim) { 943 if (isHiddenFromUserLocked()) { 944 Slog.w(TAG, "current user violation " + mService.mCurrentUserId + " trying to display " 945 + this + ", type " + mAttrs.type + ", belonging to " + mOwnerUid); 946 return false; 947 } 948 if (mPolicyVisibility && mPolicyVisibilityAfterAnim) { 949 // Already showing. 950 return false; 951 } 952 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this); 953 if (doAnimation) { 954 if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility=" 955 + mPolicyVisibility + " mAnimation=" + mWinAnimator.mAnimation); 956 if (!mService.okToDisplay()) { 957 doAnimation = false; 958 } else if (mPolicyVisibility && mWinAnimator.mAnimation == null) { 959 // Check for the case where we are currently visible and 960 // not animating; we do not want to do animation at such a 961 // point to become visible when we already are. 962 doAnimation = false; 963 } 964 } 965 mPolicyVisibility = true; 966 mPolicyVisibilityAfterAnim = true; 967 if (doAnimation) { 968 mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_ENTER, true); 969 } 970 if (requestAnim) { 971 mService.updateLayoutToAnimationLocked(); 972 } 973 return true; 974 } 975 976 @Override 977 public boolean hideLw(boolean doAnimation) { 978 return hideLw(doAnimation, true); 979 } 980 981 boolean hideLw(boolean doAnimation, boolean requestAnim) { 982 if (doAnimation) { 983 if (!mService.okToDisplay()) { 984 doAnimation = false; 985 } 986 } 987 boolean current = doAnimation ? mPolicyVisibilityAfterAnim 988 : mPolicyVisibility; 989 if (!current) { 990 // Already hiding. 991 return false; 992 } 993 if (doAnimation) { 994 mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, false); 995 if (mWinAnimator.mAnimation == null) { 996 doAnimation = false; 997 } 998 } 999 if (doAnimation) { 1000 mPolicyVisibilityAfterAnim = false; 1001 } else { 1002 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this); 1003 mPolicyVisibilityAfterAnim = false; 1004 mPolicyVisibility = false; 1005 // Window is no longer visible -- make sure if we were waiting 1006 // for it to be displayed before enabling the display, that 1007 // we allow the display to be enabled now. 1008 mService.enableScreenIfNeededLocked(); 1009 if (mService.mCurrentFocus == this) { 1010 mService.mFocusMayChange = true; 1011 } 1012 } 1013 if (requestAnim) { 1014 mService.updateLayoutToAnimationLocked(); 1015 } 1016 return true; 1017 } 1018 1019 @Override 1020 public boolean isAlive() { 1021 return mClient.asBinder().isBinderAlive(); 1022 } 1023 1024 @Override 1025 public boolean isDefaultDisplay() { 1026 return mDisplayContent.isDefaultDisplay; 1027 } 1028 1029 public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) { 1030 mShowToOwnerOnly = showToOwnerOnly; 1031 } 1032 1033 boolean isHiddenFromUserLocked() { 1034 // Save some cycles by not calling getDisplayInfo unless it is an application 1035 // window intended for all users. 1036 if (mAttrs.type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW 1037 && mAppToken != null && mAppToken.showWhenLocked) { 1038 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo(); 1039 if (isFullscreen(displayInfo.appWidth, displayInfo.appHeight)) { 1040 // Is a fullscreen window, like the clock alarm. Show to everyone. 1041 return false; 1042 } 1043 } 1044 1045 return mShowToOwnerOnly && UserHandle.getUserId(mOwnerUid) != mService.mCurrentUserId; 1046 } 1047 1048 private static void applyInsets(Region outRegion, Rect frame, Rect inset) { 1049 outRegion.set( 1050 frame.left + inset.left, frame.top + inset.top, 1051 frame.right - inset.right, frame.bottom - inset.bottom); 1052 } 1053 1054 public void getTouchableRegion(Region outRegion) { 1055 final Rect frame = mFrame; 1056 switch (mTouchableInsets) { 1057 default: 1058 case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME: 1059 outRegion.set(frame); 1060 break; 1061 case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT: 1062 applyInsets(outRegion, frame, mGivenContentInsets); 1063 break; 1064 case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE: 1065 applyInsets(outRegion, frame, mGivenVisibleInsets); 1066 break; 1067 case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: { 1068 final Region givenTouchableRegion = mGivenTouchableRegion; 1069 outRegion.set(givenTouchableRegion); 1070 outRegion.translate(frame.left, frame.top); 1071 break; 1072 } 1073 } 1074 } 1075 1076 WindowList getWindowList() { 1077 return mDisplayContent.getWindowList(); 1078 } 1079 1080 void dump(PrintWriter pw, String prefix, boolean dumpAll) { 1081 pw.print(prefix); pw.print("mDisplayId="); pw.print(mDisplayContent.getDisplayId()); 1082 pw.print(" mSession="); pw.print(mSession); 1083 pw.print(" mClient="); pw.println(mClient.asBinder()); 1084 pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid); 1085 pw.print(" mShowToOwnerOnly="); pw.println(mShowToOwnerOnly); 1086 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs); 1087 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth); 1088 pw.print(" h="); pw.print(mRequestedHeight); 1089 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 1090 if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) { 1091 pw.print(prefix); pw.print("LastRequested w="); pw.print(mLastRequestedWidth); 1092 pw.print(" h="); pw.println(mLastRequestedHeight); 1093 } 1094 if (mAttachedWindow != null || mLayoutAttached) { 1095 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow); 1096 pw.print(" mLayoutAttached="); pw.println(mLayoutAttached); 1097 } 1098 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) { 1099 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow); 1100 pw.print(" mIsWallpaper="); pw.print(mIsWallpaper); 1101 pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer); 1102 pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible); 1103 } 1104 if (dumpAll) { 1105 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer); 1106 pw.print(" mSubLayer="); pw.print(mSubLayer); 1107 pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+"); 1108 pw.print((mTargetAppToken != null ? 1109 mTargetAppToken.mAppAnimator.animLayerAdjustment 1110 : (mAppToken != null ? mAppToken.mAppAnimator.animLayerAdjustment : 0))); 1111 pw.print("="); pw.print(mWinAnimator.mAnimLayer); 1112 pw.print(" mLastLayer="); pw.println(mWinAnimator.mLastLayer); 1113 } 1114 if (dumpAll) { 1115 pw.print(prefix); pw.print("mToken="); pw.println(mToken); 1116 pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken); 1117 if (mAppToken != null) { 1118 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken); 1119 } 1120 if (mTargetAppToken != null) { 1121 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken); 1122 } 1123 pw.print(prefix); pw.print("mViewVisibility=0x"); 1124 pw.print(Integer.toHexString(mViewVisibility)); 1125 pw.print(" mHaveFrame="); pw.print(mHaveFrame); 1126 pw.print(" mObscured="); pw.println(mObscured); 1127 pw.print(prefix); pw.print("mSeq="); pw.print(mSeq); 1128 pw.print(" mSystemUiVisibility=0x"); 1129 pw.println(Integer.toHexString(mSystemUiVisibility)); 1130 } 1131 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) { 1132 pw.print(prefix); pw.print("mPolicyVisibility="); 1133 pw.print(mPolicyVisibility); 1134 pw.print(" mPolicyVisibilityAfterAnim="); 1135 pw.print(mPolicyVisibilityAfterAnim); 1136 pw.print(" mAttachedHidden="); pw.println(mAttachedHidden); 1137 } 1138 if (!mRelayoutCalled || mLayoutNeeded) { 1139 pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled); 1140 pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded); 1141 } 1142 if (mXOffset != 0 || mYOffset != 0) { 1143 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset); 1144 pw.print(" y="); pw.println(mYOffset); 1145 } 1146 if (dumpAll) { 1147 pw.print(prefix); pw.print("mGivenContentInsets="); 1148 mGivenContentInsets.printShortString(pw); 1149 pw.print(" mGivenVisibleInsets="); 1150 mGivenVisibleInsets.printShortString(pw); 1151 pw.println(); 1152 if (mTouchableInsets != 0 || mGivenInsetsPending) { 1153 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets); 1154 pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending); 1155 Region region = new Region(); 1156 getTouchableRegion(region); 1157 pw.print(prefix); pw.print("touchable region="); pw.println(region); 1158 } 1159 pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration); 1160 } 1161 pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface); 1162 pw.print(" mShownFrame="); mShownFrame.printShortString(pw); 1163 pw.print(" isReadyForDisplay()="); pw.println(isReadyForDisplay()); 1164 if (dumpAll) { 1165 pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw); 1166 pw.print(" last="); mLastFrame.printShortString(pw); 1167 pw.println(); 1168 pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw); 1169 pw.print(" last="); mLastSystemDecorRect.printShortString(pw); 1170 pw.println(); 1171 } 1172 if (mEnforceSizeCompat) { 1173 pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw); 1174 pw.println(); 1175 } 1176 if (dumpAll) { 1177 pw.print(prefix); pw.print("Frames: containing="); 1178 mContainingFrame.printShortString(pw); 1179 pw.print(" parent="); mParentFrame.printShortString(pw); 1180 pw.print(" display="); mDisplayFrame.printShortString(pw); 1181 pw.println(); 1182 pw.print(prefix); pw.print(" content="); mContentFrame.printShortString(pw); 1183 pw.print(" visible="); mVisibleFrame.printShortString(pw); 1184 pw.println(); 1185 pw.print(prefix); pw.print("Cur insets: content="); 1186 mContentInsets.printShortString(pw); 1187 pw.print(" visible="); mVisibleInsets.printShortString(pw); 1188 pw.println(); 1189 pw.print(prefix); pw.print("Lst insets: content="); 1190 mLastContentInsets.printShortString(pw); 1191 pw.print(" visible="); mLastVisibleInsets.printShortString(pw); 1192 pw.println(); 1193 } 1194 mWinAnimator.dump(pw, prefix, dumpAll); 1195 if (mExiting || mRemoveOnExit || mDestroying || mRemoved) { 1196 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting); 1197 pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit); 1198 pw.print(" mDestroying="); pw.print(mDestroying); 1199 pw.print(" mRemoved="); pw.println(mRemoved); 1200 } 1201 if (mOrientationChanging || mAppFreezing || mTurnOnScreen) { 1202 pw.print(prefix); pw.print("mOrientationChanging="); 1203 pw.print(mOrientationChanging); 1204 pw.print(" mAppFreezing="); pw.print(mAppFreezing); 1205 pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen); 1206 } 1207 if (mHScale != 1 || mVScale != 1) { 1208 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale); 1209 pw.print(" mVScale="); pw.println(mVScale); 1210 } 1211 if (mWallpaperX != -1 || mWallpaperY != -1) { 1212 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX); 1213 pw.print(" mWallpaperY="); pw.println(mWallpaperY); 1214 } 1215 if (mWallpaperXStep != -1 || mWallpaperYStep != -1) { 1216 pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep); 1217 pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep); 1218 } 1219 } 1220 1221 String makeInputChannelName() { 1222 return Integer.toHexString(System.identityHashCode(this)) 1223 + " " + mAttrs.getTitle(); 1224 } 1225 1226 @Override 1227 public String toString() { 1228 if (mStringNameCache == null || mLastTitle != mAttrs.getTitle() 1229 || mWasPaused != mToken.paused) { 1230 mLastTitle = mAttrs.getTitle(); 1231 mWasPaused = mToken.paused; 1232 mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this)) 1233 + " u" + UserHandle.getUserId(mSession.mUid) 1234 + " " + mLastTitle + (mWasPaused ? " PAUSED}" : "}"); 1235 } 1236 return mStringNameCache; 1237 } 1238} 1239