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