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