Session.java revision 943002b47346ea82b4e69dca033cc03086969dd1
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.Manifest.permission.INTERNAL_SYSTEM_WINDOW; 20import static android.content.pm.PackageManager.PERMISSION_GRANTED; 21import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 22import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; 23import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG; 24import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; 25import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 26import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 27import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 28 29import android.content.ClipData; 30import android.content.Context; 31import android.content.res.Configuration; 32import android.graphics.Rect; 33import android.graphics.Region; 34import android.os.Binder; 35import android.os.Bundle; 36import android.os.IBinder; 37import android.os.Parcel; 38import android.os.Process; 39import android.os.RemoteException; 40import android.os.ServiceManager; 41import android.os.UserHandle; 42import android.util.Slog; 43import android.view.Display; 44import android.view.IWindow; 45import android.view.IWindowId; 46import android.view.IWindowSession; 47import android.view.IWindowSessionCallback; 48import android.view.InputChannel; 49import android.view.Surface; 50import android.view.SurfaceControl; 51import android.view.SurfaceSession; 52import android.view.WindowManager; 53 54import com.android.internal.view.IInputContext; 55import com.android.internal.view.IInputMethodClient; 56import com.android.internal.view.IInputMethodManager; 57import com.android.server.wm.WindowManagerService.H; 58 59import java.io.PrintWriter; 60import java.util.HashSet; 61import java.util.Set; 62 63/** 64 * This class represents an active client session. There is generally one 65 * Session object per process that is interacting with the window manager. 66 */ 67// Needs to be public and not final so we can mock during tests...sucks I know :( 68public class Session extends IWindowSession.Stub 69 implements IBinder.DeathRecipient { 70 final WindowManagerService mService; 71 final IWindowSessionCallback mCallback; 72 final IInputMethodClient mClient; 73 final int mUid; 74 final int mPid; 75 private final String mStringName; 76 SurfaceSession mSurfaceSession; 77 private int mNumWindow = 0; 78 // Set of visible application overlay window surfaces connected to this session. 79 private final Set<WindowSurfaceController> mAppOverlaySurfaces = new HashSet<>(); 80 // Set of visible alert window surfaces connected to this session. 81 private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>(); 82 final boolean mCanAddInternalSystemWindow; 83 private boolean mClientDead = false; 84 private float mLastReportedAnimatorScale; 85 86 public Session(WindowManagerService service, IWindowSessionCallback callback, 87 IInputMethodClient client, IInputContext inputContext) { 88 mService = service; 89 mCallback = callback; 90 mClient = client; 91 mUid = Binder.getCallingUid(); 92 mPid = Binder.getCallingPid(); 93 mLastReportedAnimatorScale = service.getCurrentAnimatorScale(); 94 mCanAddInternalSystemWindow = service.mContext.checkCallingPermission( 95 INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED; 96 StringBuilder sb = new StringBuilder(); 97 sb.append("Session{"); 98 sb.append(Integer.toHexString(System.identityHashCode(this))); 99 sb.append(" "); 100 sb.append(mPid); 101 if (mUid < Process.FIRST_APPLICATION_UID) { 102 sb.append(":"); 103 sb.append(mUid); 104 } else { 105 sb.append(":u"); 106 sb.append(UserHandle.getUserId(mUid)); 107 sb.append('a'); 108 sb.append(UserHandle.getAppId(mUid)); 109 } 110 sb.append("}"); 111 mStringName = sb.toString(); 112 113 synchronized (mService.mWindowMap) { 114 if (mService.mInputMethodManager == null && mService.mHaveInputMethods) { 115 IBinder b = ServiceManager.getService( 116 Context.INPUT_METHOD_SERVICE); 117 mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b); 118 } 119 } 120 long ident = Binder.clearCallingIdentity(); 121 try { 122 // Note: it is safe to call in to the input method manager 123 // here because we are not holding our lock. 124 if (mService.mInputMethodManager != null) { 125 mService.mInputMethodManager.addClient(client, inputContext, 126 mUid, mPid); 127 } else { 128 client.setUsingInputMethod(false); 129 } 130 client.asBinder().linkToDeath(this, 0); 131 } catch (RemoteException e) { 132 // The caller has died, so we can just forget about this. 133 try { 134 if (mService.mInputMethodManager != null) { 135 mService.mInputMethodManager.removeClient(client); 136 } 137 } catch (RemoteException ee) { 138 } 139 } finally { 140 Binder.restoreCallingIdentity(ident); 141 } 142 } 143 144 @Override 145 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 146 throws RemoteException { 147 try { 148 return super.onTransact(code, data, reply, flags); 149 } catch (RuntimeException e) { 150 // Log all 'real' exceptions thrown to the caller 151 if (!(e instanceof SecurityException)) { 152 Slog.wtf(TAG_WM, "Window Session Crash", e); 153 } 154 throw e; 155 } 156 } 157 158 public void binderDied() { 159 // Note: it is safe to call in to the input method manager 160 // here because we are not holding our lock. 161 try { 162 if (mService.mInputMethodManager != null) { 163 mService.mInputMethodManager.removeClient(mClient); 164 } 165 } catch (RemoteException e) { 166 } 167 synchronized(mService.mWindowMap) { 168 mClient.asBinder().unlinkToDeath(this, 0); 169 mClientDead = true; 170 killSessionLocked(); 171 } 172 } 173 174 @Override 175 public int add(IWindow window, int seq, WindowManager.LayoutParams attrs, 176 int viewVisibility, Rect outContentInsets, Rect outStableInsets, 177 InputChannel outInputChannel) { 178 return addToDisplay(window, seq, attrs, viewVisibility, Display.DEFAULT_DISPLAY, 179 outContentInsets, outStableInsets, null /* outOutsets */, outInputChannel); 180 } 181 182 @Override 183 public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, 184 int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, 185 Rect outOutsets, InputChannel outInputChannel) { 186 return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, 187 outContentInsets, outStableInsets, outOutsets, outInputChannel); 188 } 189 190 @Override 191 public int addWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs, 192 int viewVisibility, Rect outContentInsets, Rect outStableInsets) { 193 return addToDisplayWithoutInputChannel(window, seq, attrs, viewVisibility, 194 Display.DEFAULT_DISPLAY, outContentInsets, outStableInsets); 195 } 196 197 @Override 198 public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs, 199 int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets) { 200 return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, 201 outContentInsets, outStableInsets, null /* outOutsets */, null); 202 } 203 204 public void remove(IWindow window) { 205 mService.removeWindow(this, window); 206 } 207 208 @Override 209 public void repositionChild(IWindow window, int left, int top, int right, int bottom, 210 long deferTransactionUntilFrame, Rect outFrame) { 211 mService.repositionChild(this, window, left, top, right, bottom, 212 deferTransactionUntilFrame, outFrame); 213 } 214 215 @Override 216 public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) { 217 mService.setWillReplaceWindows(appToken, childrenOnly); 218 } 219 220 public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, 221 int requestedWidth, int requestedHeight, int viewFlags, 222 int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, 223 Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame, 224 Configuration outConfig, Surface outSurface) { 225 if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from " 226 + Binder.getCallingPid()); 227 int res = mService.relayoutWindow(this, window, seq, attrs, 228 requestedWidth, requestedHeight, viewFlags, flags, 229 outFrame, outOverscanInsets, outContentInsets, outVisibleInsets, 230 outStableInsets, outsets, outBackdropFrame, outConfig, outSurface); 231 if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to " 232 + Binder.getCallingPid()); 233 return res; 234 } 235 236 public void performDeferredDestroy(IWindow window) { 237 mService.performDeferredDestroyWindow(this, window); 238 } 239 240 public boolean outOfMemory(IWindow window) { 241 return mService.outOfMemoryWindow(this, window); 242 } 243 244 public void setTransparentRegion(IWindow window, Region region) { 245 mService.setTransparentRegionWindow(this, window, region); 246 } 247 248 public void setInsets(IWindow window, int touchableInsets, 249 Rect contentInsets, Rect visibleInsets, Region touchableArea) { 250 mService.setInsetsWindow(this, window, touchableInsets, contentInsets, 251 visibleInsets, touchableArea); 252 } 253 254 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) { 255 mService.getWindowDisplayFrame(this, window, outDisplayFrame); 256 } 257 258 public void finishDrawing(IWindow window) { 259 if (WindowManagerService.localLOGV) Slog.v( 260 TAG_WM, "IWindow finishDrawing called for " + window); 261 mService.finishDrawingWindow(this, window); 262 } 263 264 public void setInTouchMode(boolean mode) { 265 synchronized(mService.mWindowMap) { 266 mService.mInTouchMode = mode; 267 } 268 } 269 270 public boolean getInTouchMode() { 271 synchronized(mService.mWindowMap) { 272 return mService.mInTouchMode; 273 } 274 } 275 276 public boolean performHapticFeedback(IWindow window, int effectId, 277 boolean always) { 278 synchronized(mService.mWindowMap) { 279 long ident = Binder.clearCallingIdentity(); 280 try { 281 return mService.mPolicy.performHapticFeedbackLw( 282 mService.windowForClientLocked(this, window, true), 283 effectId, always); 284 } finally { 285 Binder.restoreCallingIdentity(ident); 286 } 287 } 288 } 289 290 /* Drag/drop */ 291 public IBinder prepareDrag(IWindow window, int flags, 292 int width, int height, Surface outSurface) { 293 return mService.prepareDragSurface(window, mSurfaceSession, flags, 294 width, height, outSurface); 295 } 296 297 public boolean performDrag(IWindow window, IBinder dragToken, 298 int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, 299 ClipData data) { 300 if (DEBUG_DRAG) { 301 Slog.d(TAG_WM, "perform drag: win=" + window + " data=" + data); 302 } 303 304 synchronized (mService.mWindowMap) { 305 if (mService.mDragState == null) { 306 Slog.w(TAG_WM, "No drag prepared"); 307 throw new IllegalStateException("performDrag() without prepareDrag()"); 308 } 309 310 if (dragToken != mService.mDragState.mToken) { 311 Slog.w(TAG_WM, "Performing mismatched drag"); 312 throw new IllegalStateException("performDrag() does not match prepareDrag()"); 313 } 314 315 WindowState callingWin = mService.windowForClientLocked(null, window, false); 316 if (callingWin == null) { 317 Slog.w(TAG_WM, "Bad requesting window " + window); 318 return false; // !!! TODO: throw here? 319 } 320 321 // !!! TODO: if input is not still focused on the initiating window, fail 322 // the drag initiation (e.g. an alarm window popped up just as the application 323 // called performDrag() 324 325 mService.mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder()); 326 327 // !!! TODO: extract the current touch (x, y) in screen coordinates. That 328 // will let us eliminate the (touchX,touchY) parameters from the API. 329 330 // !!! FIXME: put all this heavy stuff onto the mH looper, as well as 331 // the actual drag event dispatch stuff in the dragstate 332 333 final DisplayContent displayContent = callingWin.getDisplayContent(); 334 if (displayContent == null) { 335 return false; 336 } 337 Display display = displayContent.getDisplay(); 338 mService.mDragState.register(display); 339 if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel, 340 mService.mDragState.getInputChannel())) { 341 Slog.e(TAG_WM, "Unable to transfer touch focus"); 342 mService.mDragState.unregister(); 343 mService.mDragState.reset(); 344 mService.mDragState = null; 345 return false; 346 } 347 348 mService.mDragState.mDisplayContent = displayContent; 349 mService.mDragState.mData = data; 350 mService.mDragState.broadcastDragStartedLw(touchX, touchY); 351 mService.mDragState.overridePointerIconLw(touchSource); 352 353 // remember the thumb offsets for later 354 mService.mDragState.mThumbOffsetX = thumbCenterX; 355 mService.mDragState.mThumbOffsetY = thumbCenterY; 356 357 // Make the surface visible at the proper location 358 final SurfaceControl surfaceControl = mService.mDragState.mSurfaceControl; 359 if (SHOW_LIGHT_TRANSACTIONS) Slog.i( 360 TAG_WM, ">>> OPEN TRANSACTION performDrag"); 361 mService.openSurfaceTransaction(); 362 try { 363 surfaceControl.setPosition(touchX - thumbCenterX, 364 touchY - thumbCenterY); 365 surfaceControl.setLayer(mService.mDragState.getDragLayerLw()); 366 surfaceControl.setLayerStack(display.getLayerStack()); 367 surfaceControl.show(); 368 } finally { 369 mService.closeSurfaceTransaction(); 370 if (SHOW_LIGHT_TRANSACTIONS) Slog.i( 371 TAG_WM, "<<< CLOSE TRANSACTION performDrag"); 372 } 373 374 mService.mDragState.notifyLocationLw(touchX, touchY); 375 } 376 377 return true; // success! 378 } 379 380 public boolean startMovingTask(IWindow window, float startX, float startY) { 381 if (DEBUG_TASK_POSITIONING) Slog.d( 382 TAG_WM, "startMovingTask: {" + startX + "," + startY + "}"); 383 384 long ident = Binder.clearCallingIdentity(); 385 try { 386 return mService.startMovingTask(window, startX, startY); 387 } finally { 388 Binder.restoreCallingIdentity(ident); 389 } 390 } 391 392 public void reportDropResult(IWindow window, boolean consumed) { 393 IBinder token = window.asBinder(); 394 if (DEBUG_DRAG) { 395 Slog.d(TAG_WM, "Drop result=" + consumed + " reported by " + token); 396 } 397 398 synchronized (mService.mWindowMap) { 399 long ident = Binder.clearCallingIdentity(); 400 try { 401 if (mService.mDragState == null) { 402 // Most likely the drop recipient ANRed and we ended the drag 403 // out from under it. Log the issue and move on. 404 Slog.w(TAG_WM, "Drop result given but no drag in progress"); 405 return; 406 } 407 408 if (mService.mDragState.mToken != token) { 409 // We're in a drag, but the wrong window has responded. 410 Slog.w(TAG_WM, "Invalid drop-result claim by " + window); 411 throw new IllegalStateException("reportDropResult() by non-recipient"); 412 } 413 414 // The right window has responded, even if it's no longer around, 415 // so be sure to halt the timeout even if the later WindowState 416 // lookup fails. 417 mService.mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder()); 418 WindowState callingWin = mService.windowForClientLocked(null, window, false); 419 if (callingWin == null) { 420 Slog.w(TAG_WM, "Bad result-reporting window " + window); 421 return; // !!! TODO: throw here? 422 } 423 424 mService.mDragState.mDragResult = consumed; 425 mService.mDragState.endDragLw(); 426 } finally { 427 Binder.restoreCallingIdentity(ident); 428 } 429 } 430 } 431 432 public void cancelDragAndDrop(IBinder dragToken) { 433 if (DEBUG_DRAG) { 434 Slog.d(TAG_WM, "cancelDragAndDrop"); 435 } 436 437 synchronized (mService.mWindowMap) { 438 long ident = Binder.clearCallingIdentity(); 439 try { 440 if (mService.mDragState == null) { 441 Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()"); 442 throw new IllegalStateException("cancelDragAndDrop() without prepareDrag()"); 443 } 444 445 if (mService.mDragState.mToken != dragToken) { 446 Slog.w(TAG_WM, 447 "cancelDragAndDrop() does not match prepareDrag()"); 448 throw new IllegalStateException( 449 "cancelDragAndDrop() does not match prepareDrag()"); 450 } 451 452 mService.mDragState.mDragResult = false; 453 mService.mDragState.cancelDragLw(); 454 } finally { 455 Binder.restoreCallingIdentity(ident); 456 } 457 } 458 } 459 460 public void dragRecipientEntered(IWindow window) { 461 if (DEBUG_DRAG) { 462 Slog.d(TAG_WM, "Drag into new candidate view @ " + window.asBinder()); 463 } 464 } 465 466 public void dragRecipientExited(IWindow window) { 467 if (DEBUG_DRAG) { 468 Slog.d(TAG_WM, "Drag from old candidate view @ " + window.asBinder()); 469 } 470 } 471 472 public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) { 473 synchronized(mService.mWindowMap) { 474 long ident = Binder.clearCallingIdentity(); 475 try { 476 mService.mRoot.mWallpaperController.setWindowWallpaperPosition( 477 mService.windowForClientLocked(this, window, true), 478 x, y, xStep, yStep); 479 } finally { 480 Binder.restoreCallingIdentity(ident); 481 } 482 } 483 } 484 485 public void wallpaperOffsetsComplete(IBinder window) { 486 synchronized (mService.mWindowMap) { 487 mService.mRoot.mWallpaperController.wallpaperOffsetsComplete(window); 488 } 489 } 490 491 public void setWallpaperDisplayOffset(IBinder window, int x, int y) { 492 synchronized(mService.mWindowMap) { 493 long ident = Binder.clearCallingIdentity(); 494 try { 495 mService.mRoot.mWallpaperController.setWindowWallpaperDisplayOffset( 496 mService.windowForClientLocked(this, window, true), x, y); 497 } finally { 498 Binder.restoreCallingIdentity(ident); 499 } 500 } 501 } 502 503 public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y, 504 int z, Bundle extras, boolean sync) { 505 synchronized(mService.mWindowMap) { 506 long ident = Binder.clearCallingIdentity(); 507 try { 508 return mService.mRoot.mWallpaperController.sendWindowWallpaperCommand( 509 mService.windowForClientLocked(this, window, true), 510 action, x, y, z, extras, sync); 511 } finally { 512 Binder.restoreCallingIdentity(ident); 513 } 514 } 515 } 516 517 public void wallpaperCommandComplete(IBinder window, Bundle result) { 518 synchronized (mService.mWindowMap) { 519 mService.mRoot.mWallpaperController.wallpaperCommandComplete(window); 520 } 521 } 522 523 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { 524 synchronized(mService.mWindowMap) { 525 final long identity = Binder.clearCallingIdentity(); 526 try { 527 mService.onRectangleOnScreenRequested(token, rectangle); 528 } finally { 529 Binder.restoreCallingIdentity(identity); 530 } 531 } 532 } 533 534 public IWindowId getWindowId(IBinder window) { 535 return mService.getWindowId(window); 536 } 537 538 @Override 539 public void pokeDrawLock(IBinder window) { 540 final long identity = Binder.clearCallingIdentity(); 541 try { 542 mService.pokeDrawLock(this, window); 543 } finally { 544 Binder.restoreCallingIdentity(identity); 545 } 546 } 547 548 @Override 549 public void updatePointerIcon(IWindow window) { 550 final long identity = Binder.clearCallingIdentity(); 551 try { 552 mService.updatePointerIcon(window); 553 } finally { 554 Binder.restoreCallingIdentity(identity); 555 } 556 } 557 558 void windowAddedLocked() { 559 if (mSurfaceSession == null) { 560 if (WindowManagerService.localLOGV) Slog.v( 561 TAG_WM, "First window added to " + this + ", creating SurfaceSession"); 562 mSurfaceSession = new SurfaceSession(); 563 if (SHOW_TRANSACTIONS) Slog.i( 564 TAG_WM, " NEW SURFACE SESSION " + mSurfaceSession); 565 mService.mSessions.add(this); 566 if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) { 567 mService.dispatchNewAnimatorScaleLocked(this); 568 } 569 } 570 mNumWindow++; 571 } 572 573 void windowRemovedLocked() { 574 mNumWindow--; 575 killSessionLocked(); 576 } 577 578 579 void onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController, 580 boolean visible, int type) { 581 582 if (!isSystemAlertWindowType(type)) { 583 return; 584 } 585 586 boolean changed; 587 588 if (!mCanAddInternalSystemWindow) { 589 // We want to track non-system signature apps adding alert windows so we can post an 590 // on-going notification for the user to control their visibility. 591 if (visible) { 592 changed = mAlertWindowSurfaces.add(surfaceController); 593 } else { 594 changed = mAlertWindowSurfaces.remove(surfaceController); 595 } 596 597 if (changed) { 598 // TODO: Update notification. 599 } 600 } 601 602 if (type != TYPE_APPLICATION_OVERLAY) { 603 return; 604 } 605 606 if (visible) { 607 changed = mAppOverlaySurfaces.add(surfaceController); 608 } else { 609 changed = mAppOverlaySurfaces.remove(surfaceController); 610 } 611 612 if (changed) { 613 // Notify activity manager of changes to app overlay windows so it can adjust the 614 // importance score for the process. 615 setHasOverlayUi(!mAppOverlaySurfaces.isEmpty()); 616 } 617 } 618 619 private void killSessionLocked() { 620 if (mNumWindow > 0 || !mClientDead) { 621 return; 622 } 623 624 mService.mSessions.remove(this); 625 if (mSurfaceSession == null) { 626 return; 627 } 628 629 if (WindowManagerService.localLOGV) Slog.v(TAG_WM, "Last window removed from " + this 630 + ", destroying " + mSurfaceSession); 631 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " KILL SURFACE SESSION " + mSurfaceSession); 632 try { 633 mSurfaceSession.kill(); 634 } catch (Exception e) { 635 Slog.w(TAG_WM, "Exception thrown when killing surface session " + mSurfaceSession 636 + " in session " + this + ": " + e.toString()); 637 } 638 mSurfaceSession = null; 639 setHasOverlayUi(false); 640 // TODO: Update notification 641 } 642 643 private void setHasOverlayUi(boolean hasOverlayUi) { 644 mService.mH.obtainMessage(H.SET_HAS_OVERLAY_UI, mPid, hasOverlayUi ? 1 : 0).sendToTarget(); 645 } 646 647 void dump(PrintWriter pw, String prefix) { 648 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow); 649 pw.print(" mAppOverlaySurfaces="); pw.print(mAppOverlaySurfaces); 650 pw.print(" mAlertWindowSurfaces="); pw.print(mAlertWindowSurfaces); 651 pw.print(" mClientDead="); pw.print(mClientDead); 652 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession); 653 } 654 655 @Override 656 public String toString() { 657 return mStringName; 658 } 659} 660