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 27 import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; 28 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; 29 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; 30 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 31 32 import android.annotation.Nullable; 33 import android.content.ClipData; 34 import android.graphics.Point; 35 import android.graphics.Rect; 36 import android.graphics.Region; 37 import android.os.Binder; 38 import android.os.Bundle; 39 import android.os.IBinder; 40 import android.os.Parcel; 41 import android.os.Process; 42 import android.os.RemoteException; 43 import android.os.Trace; 44 import android.os.UserHandle; 45 import android.util.ArraySet; 46 import android.util.MergedConfiguration; 47 import android.util.Slog; 48 import android.view.DisplayCutout; 49 import android.view.IWindow; 50 import android.view.IWindowId; 51 import android.view.IWindowSession; 52 import android.view.IWindowSessionCallback; 53 import android.view.InputChannel; 54 import android.view.InsetsSourceControl; 55 import android.view.InsetsState; 56 import android.view.SurfaceControl; 57 import android.view.SurfaceSession; 58 import android.view.WindowManager; 59 60 import com.android.internal.os.logging.MetricsLoggerWrapper; 61 import com.android.server.protolog.common.ProtoLog; 62 import com.android.server.wm.WindowManagerService.H; 63 64 import java.io.PrintWriter; 65 import java.util.List; 66 import java.util.function.BiConsumer; 67 68 /** 69 * This class represents an active client session. There is generally one 70 * Session object per process that is interacting with the window manager. 71 */ 72 class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { 73 final WindowManagerService mService; 74 final IWindowSessionCallback mCallback; 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 ArraySet<WindowSurfaceController> mAppOverlaySurfaces = new ArraySet<>(); 82 // Set of visible alert window surfaces connected to this session. 83 private final ArraySet<WindowSurfaceController> mAlertWindowSurfaces = new ArraySet<>(); 84 private final DragDropController mDragDropController; 85 final boolean mCanAddInternalSystemWindow; 86 final boolean mCanHideNonSystemOverlayWindows; 87 final boolean mCanAcquireSleepToken; 88 private AlertWindowNotification mAlertWindowNotification; 89 private boolean mShowingAlertWindowNotificationAllowed; 90 private boolean mClientDead = false; 91 private float mLastReportedAnimatorScale; 92 private String mPackageName; 93 private String mRelayoutTag; 94 private final InsetsSourceControl[] mDummyControls = new InsetsSourceControl[0]; 95 Session(WindowManagerService service, IWindowSessionCallback callback)96 public Session(WindowManagerService service, IWindowSessionCallback callback) { 97 mService = service; 98 mCallback = callback; 99 mUid = Binder.getCallingUid(); 100 mPid = Binder.getCallingPid(); 101 mLastReportedAnimatorScale = service.getCurrentAnimatorScale(); 102 mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission( 103 INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED; 104 mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission( 105 HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED; 106 mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER) 107 == PERMISSION_GRANTED; 108 mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications; 109 mDragDropController = mService.mDragDropController; 110 StringBuilder sb = new StringBuilder(); 111 sb.append("Session{"); 112 sb.append(Integer.toHexString(System.identityHashCode(this))); 113 sb.append(" "); 114 sb.append(mPid); 115 if (mUid < Process.FIRST_APPLICATION_UID) { 116 sb.append(":"); 117 sb.append(mUid); 118 } else { 119 sb.append(":u"); 120 sb.append(UserHandle.getUserId(mUid)); 121 sb.append('a'); 122 sb.append(UserHandle.getAppId(mUid)); 123 } 124 sb.append("}"); 125 mStringName = sb.toString(); 126 127 try { 128 mCallback.asBinder().linkToDeath(this, 0); 129 } catch (RemoteException e) { 130 // The caller has died, so we can just forget about this. 131 // Hmmm, should we call killSessionLocked()?? 132 } 133 } 134 135 @Override onTransact(int code, Parcel data, Parcel reply, int flags)136 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 137 throws RemoteException { 138 try { 139 return super.onTransact(code, data, reply, flags); 140 } catch (RuntimeException e) { 141 // Log all 'real' exceptions thrown to the caller 142 if (!(e instanceof SecurityException)) { 143 Slog.wtf(TAG_WM, "Window Session Crash", e); 144 } 145 throw e; 146 } 147 } 148 149 @Override binderDied()150 public void binderDied() { 151 synchronized (mService.mGlobalLock) { 152 mCallback.asBinder().unlinkToDeath(this, 0); 153 mClientDead = true; 154 killSessionLocked(); 155 } 156 } 157 158 @Override addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets, Rect outStableInsets, DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls)159 public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, 160 int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets, 161 Rect outStableInsets, 162 DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel, 163 InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) { 164 return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame, 165 outContentInsets, outStableInsets, outDisplayCutout, outInputChannel, 166 outInsetsState, outActiveControls, UserHandle.getUserId(mUid)); 167 } 168 169 170 @Override addToDisplayAsUser(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, int userId, Rect outFrame, Rect outContentInsets, Rect outStableInsets, DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls)171 public int addToDisplayAsUser(IWindow window, int seq, WindowManager.LayoutParams attrs, 172 int viewVisibility, int displayId, int userId, Rect outFrame, 173 Rect outContentInsets, Rect outStableInsets, 174 DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel, 175 InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) { 176 return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame, 177 outContentInsets, outStableInsets, outDisplayCutout, outInputChannel, 178 outInsetsState, outActiveControls, userId); 179 } 180 181 @Override addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, InsetsState outInsetsState)182 public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs, 183 int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, 184 InsetsState outInsetsState) { 185 return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, 186 new Rect() /* outFrame */, outContentInsets, outStableInsets, 187 new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */, 188 outInsetsState, mDummyControls, UserHandle.getUserId(mUid)); 189 } 190 191 @Override remove(IWindow window)192 public void remove(IWindow window) { 193 mService.removeWindow(this, window); 194 } 195 196 @Override prepareToReplaceWindows(IBinder appToken, boolean childrenOnly)197 public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) { 198 mService.setWillReplaceWindows(appToken, childrenOnly); 199 } 200 201 @Override relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber, Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outBackdropFrame, DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls, Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl)202 public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, 203 int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber, 204 Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, 205 Rect outStableInsets, Rect outBackdropFrame, 206 DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration, 207 SurfaceControl outSurfaceControl, InsetsState outInsetsState, 208 InsetsSourceControl[] outActiveControls, Point outSurfaceSize, 209 SurfaceControl outBLASTSurfaceControl) { 210 if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from " 211 + Binder.getCallingPid()); 212 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag); 213 int res = mService.relayoutWindow(this, window, seq, attrs, 214 requestedWidth, requestedHeight, viewFlags, flags, frameNumber, 215 outFrame, outContentInsets, outVisibleInsets, 216 outStableInsets, outBackdropFrame, cutout, 217 mergedConfiguration, outSurfaceControl, outInsetsState, outActiveControls, 218 outSurfaceSize, outBLASTSurfaceControl); 219 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 220 if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to " 221 + Binder.getCallingPid()); 222 return res; 223 } 224 225 @Override outOfMemory(IWindow window)226 public boolean outOfMemory(IWindow window) { 227 return mService.outOfMemoryWindow(this, window); 228 } 229 230 @Override setTransparentRegion(IWindow window, Region region)231 public void setTransparentRegion(IWindow window, Region region) { 232 mService.setTransparentRegionWindow(this, window, region); 233 } 234 235 @Override setInsets(IWindow window, int touchableInsets, Rect contentInsets, Rect visibleInsets, Region touchableArea)236 public void setInsets(IWindow window, int touchableInsets, 237 Rect contentInsets, Rect visibleInsets, Region touchableArea) { 238 mService.setInsetsWindow(this, window, touchableInsets, contentInsets, 239 visibleInsets, touchableArea); 240 } 241 242 @Override getDisplayFrame(IWindow window, Rect outDisplayFrame)243 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) { 244 mService.getWindowDisplayFrame(this, window, outDisplayFrame); 245 } 246 247 @Override finishDrawing(IWindow window, @Nullable SurfaceControl.Transaction postDrawTransaction)248 public void finishDrawing(IWindow window, 249 @Nullable SurfaceControl.Transaction postDrawTransaction) { 250 if (DEBUG) Slog.v(TAG_WM, "IWindow finishDrawing called for " + window); 251 mService.finishDrawingWindow(this, window, postDrawTransaction); 252 } 253 254 @Override setInTouchMode(boolean mode)255 public void setInTouchMode(boolean mode) { 256 mService.setInTouchMode(mode); 257 } 258 259 @Override getInTouchMode()260 public boolean getInTouchMode() { 261 return mService.getInTouchMode(); 262 } 263 264 @Override performHapticFeedback(int effectId, boolean always)265 public boolean performHapticFeedback(int effectId, boolean always) { 266 long ident = Binder.clearCallingIdentity(); 267 try { 268 return mService.mPolicy.performHapticFeedback(mUid, mPackageName, 269 effectId, always, null); 270 } finally { 271 Binder.restoreCallingIdentity(ident); 272 } 273 } 274 275 /* Drag/drop */ 276 277 @Override performDrag(IWindow window, int flags, SurfaceControl surface, int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data)278 public IBinder performDrag(IWindow window, int flags, SurfaceControl surface, int touchSource, 279 float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data) { 280 final long ident = Binder.clearCallingIdentity(); 281 try { 282 return mDragDropController.performDrag(mSurfaceSession, mPid, mUid, window, 283 flags, surface, touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data); 284 } finally { 285 Binder.restoreCallingIdentity(ident); 286 } 287 } 288 289 @Override reportDropResult(IWindow window, boolean consumed)290 public void reportDropResult(IWindow window, boolean consumed) { 291 final long ident = Binder.clearCallingIdentity(); 292 try { 293 mDragDropController.reportDropResult(window, consumed); 294 } finally { 295 Binder.restoreCallingIdentity(ident); 296 } 297 } 298 299 @Override cancelDragAndDrop(IBinder dragToken, boolean skipAnimation)300 public void cancelDragAndDrop(IBinder dragToken, boolean skipAnimation) { 301 final long ident = Binder.clearCallingIdentity(); 302 try { 303 mDragDropController.cancelDragAndDrop(dragToken, skipAnimation); 304 } finally { 305 Binder.restoreCallingIdentity(ident); 306 } 307 } 308 309 @Override dragRecipientEntered(IWindow window)310 public void dragRecipientEntered(IWindow window) { 311 mDragDropController.dragRecipientEntered(window); 312 } 313 314 @Override dragRecipientExited(IWindow window)315 public void dragRecipientExited(IWindow window) { 316 mDragDropController.dragRecipientExited(window); 317 } 318 319 @Override startMovingTask(IWindow window, float startX, float startY)320 public boolean startMovingTask(IWindow window, float startX, float startY) { 321 if (DEBUG_TASK_POSITIONING) Slog.d( 322 TAG_WM, "startMovingTask: {" + startX + "," + startY + "}"); 323 324 long ident = Binder.clearCallingIdentity(); 325 try { 326 return mService.mTaskPositioningController.startMovingTask(window, startX, startY); 327 } finally { 328 Binder.restoreCallingIdentity(ident); 329 } 330 } 331 332 @Override finishMovingTask(IWindow window)333 public void finishMovingTask(IWindow window) { 334 if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "finishMovingTask"); 335 336 long ident = Binder.clearCallingIdentity(); 337 try { 338 mService.mTaskPositioningController.finishTaskPositioning(window); 339 } finally { 340 Binder.restoreCallingIdentity(ident); 341 } 342 } 343 344 @Override reportSystemGestureExclusionChanged(IWindow window, List<Rect> exclusionRects)345 public void reportSystemGestureExclusionChanged(IWindow window, List<Rect> exclusionRects) { 346 long ident = Binder.clearCallingIdentity(); 347 try { 348 mService.reportSystemGestureExclusionChanged(this, window, exclusionRects); 349 } finally { 350 Binder.restoreCallingIdentity(ident); 351 } 352 } 353 actionOnWallpaper(IBinder window, BiConsumer<WallpaperController, WindowState> action)354 private void actionOnWallpaper(IBinder window, 355 BiConsumer<WallpaperController, WindowState> action) { 356 final WindowState windowState = mService.windowForClientLocked(this, window, true); 357 action.accept(windowState.getDisplayContent().mWallpaperController, windowState); 358 } 359 360 @Override setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep)361 public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) { 362 synchronized (mService.mGlobalLock) { 363 long ident = Binder.clearCallingIdentity(); 364 try { 365 actionOnWallpaper(window, (wpController, windowState) -> 366 wpController.setWindowWallpaperPosition(windowState, x, y, xStep, yStep)); 367 } finally { 368 Binder.restoreCallingIdentity(ident); 369 } 370 } 371 } 372 373 @Override setWallpaperZoomOut(IBinder window, float zoom)374 public void setWallpaperZoomOut(IBinder window, float zoom) { 375 if (Float.compare(0f, zoom) > 0 || Float.compare(1f, zoom) < 0 || Float.isNaN(zoom)) { 376 throw new IllegalArgumentException("Zoom must be a valid float between 0 and 1: " 377 + zoom); 378 } 379 synchronized (mService.mGlobalLock) { 380 long ident = Binder.clearCallingIdentity(); 381 try { 382 actionOnWallpaper(window, (wpController, windowState) -> 383 wpController.setWallpaperZoomOut(windowState, zoom)); 384 } finally { 385 Binder.restoreCallingIdentity(ident); 386 } 387 } 388 } 389 390 @Override setShouldZoomOutWallpaper(IBinder window, boolean shouldZoom)391 public void setShouldZoomOutWallpaper(IBinder window, boolean shouldZoom) { 392 synchronized (mService.mGlobalLock) { 393 actionOnWallpaper(window, (wpController, windowState) -> 394 wpController.setShouldZoomOutWallpaper(windowState, shouldZoom)); 395 } 396 } 397 398 @Override wallpaperOffsetsComplete(IBinder window)399 public void wallpaperOffsetsComplete(IBinder window) { 400 synchronized (mService.mGlobalLock) { 401 actionOnWallpaper(window, (wpController, windowState) -> 402 wpController.wallpaperOffsetsComplete(window)); 403 } 404 } 405 406 @Override setWallpaperDisplayOffset(IBinder window, int x, int y)407 public void setWallpaperDisplayOffset(IBinder window, int x, int y) { 408 synchronized (mService.mGlobalLock) { 409 long ident = Binder.clearCallingIdentity(); 410 try { 411 actionOnWallpaper(window, (wpController, windowState) -> 412 wpController.setWindowWallpaperDisplayOffset(windowState, x, y)); 413 } finally { 414 Binder.restoreCallingIdentity(ident); 415 } 416 } 417 } 418 419 @Override sendWallpaperCommand(IBinder window, String action, int x, int y, int z, Bundle extras, boolean sync)420 public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y, 421 int z, Bundle extras, boolean sync) { 422 synchronized (mService.mGlobalLock) { 423 long ident = Binder.clearCallingIdentity(); 424 try { 425 final WindowState windowState = mService.windowForClientLocked(this, window, true); 426 return windowState.getDisplayContent().mWallpaperController 427 .sendWindowWallpaperCommand(windowState, action, x, y, z, extras, sync); 428 } finally { 429 Binder.restoreCallingIdentity(ident); 430 } 431 } 432 } 433 434 @Override wallpaperCommandComplete(IBinder window, Bundle result)435 public void wallpaperCommandComplete(IBinder window, Bundle result) { 436 synchronized (mService.mGlobalLock) { 437 actionOnWallpaper(window, (wpController, windowState) -> 438 wpController.wallpaperCommandComplete(window)); 439 } 440 } 441 442 @Override onRectangleOnScreenRequested(IBinder token, Rect rectangle)443 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { 444 synchronized (mService.mGlobalLock) { 445 final long identity = Binder.clearCallingIdentity(); 446 try { 447 mService.onRectangleOnScreenRequested(token, rectangle); 448 } finally { 449 Binder.restoreCallingIdentity(identity); 450 } 451 } 452 } 453 454 @Override getWindowId(IBinder window)455 public IWindowId getWindowId(IBinder window) { 456 return mService.getWindowId(window); 457 } 458 459 @Override pokeDrawLock(IBinder window)460 public void pokeDrawLock(IBinder window) { 461 final long identity = Binder.clearCallingIdentity(); 462 try { 463 mService.pokeDrawLock(this, window); 464 } finally { 465 Binder.restoreCallingIdentity(identity); 466 } 467 } 468 469 @Override updatePointerIcon(IWindow window)470 public void updatePointerIcon(IWindow window) { 471 final long identity = Binder.clearCallingIdentity(); 472 try { 473 mService.updatePointerIcon(window); 474 } finally { 475 Binder.restoreCallingIdentity(identity); 476 } 477 } 478 479 @Override reparentDisplayContent(IWindow window, SurfaceControl sc, int displayId)480 public void reparentDisplayContent(IWindow window, SurfaceControl sc, int displayId) { 481 mService.reparentDisplayContent(window, sc, displayId); 482 } 483 484 @Override updateDisplayContentLocation(IWindow window, int x, int y, int displayId)485 public void updateDisplayContentLocation(IWindow window, int x, int y, int displayId) { 486 mService.updateDisplayContentLocation(window, x, y, displayId); 487 } 488 489 @Override updateTapExcludeRegion(IWindow window, Region region)490 public void updateTapExcludeRegion(IWindow window, Region region) { 491 final long identity = Binder.clearCallingIdentity(); 492 try { 493 mService.updateTapExcludeRegion(window, region); 494 } finally { 495 Binder.restoreCallingIdentity(identity); 496 } 497 } 498 499 @Override insetsModified(IWindow window, InsetsState state)500 public void insetsModified(IWindow window, InsetsState state) { 501 synchronized (mService.mGlobalLock) { 502 final WindowState windowState = mService.windowForClientLocked(this, window, 503 false /* throwOnError */); 504 if (windowState != null) { 505 windowState.updateRequestedInsetsState(state); 506 windowState.getDisplayContent().getInsetsPolicy().onInsetsModified( 507 windowState, state); 508 } 509 } 510 } 511 windowAddedLocked(String packageName)512 void windowAddedLocked(String packageName) { 513 mPackageName = packageName; 514 mRelayoutTag = "relayoutWindow: " + mPackageName; 515 if (mSurfaceSession == null) { 516 if (DEBUG) { 517 Slog.v(TAG_WM, "First window added to " + this + ", creating SurfaceSession"); 518 } 519 mSurfaceSession = new SurfaceSession(); 520 ProtoLog.i(WM_SHOW_TRANSACTIONS, " NEW SURFACE SESSION %s", mSurfaceSession); 521 mService.mSessions.add(this); 522 if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) { 523 mService.dispatchNewAnimatorScaleLocked(this); 524 } 525 } 526 mNumWindow++; 527 } 528 windowRemovedLocked()529 void windowRemovedLocked() { 530 mNumWindow--; 531 killSessionLocked(); 532 } 533 534 onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController, boolean visible, int type)535 void onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController, 536 boolean visible, int type) { 537 538 if (!isSystemAlertWindowType(type)) { 539 return; 540 } 541 542 boolean changed; 543 544 if (!mCanAddInternalSystemWindow) { 545 // We want to track non-system signature apps adding alert windows so we can post an 546 // on-going notification for the user to control their visibility. 547 if (visible) { 548 changed = mAlertWindowSurfaces.add(surfaceController); 549 MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type, true); 550 } else { 551 changed = mAlertWindowSurfaces.remove(surfaceController); 552 MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type, true); 553 } 554 555 if (changed) { 556 if (mAlertWindowSurfaces.isEmpty()) { 557 cancelAlertWindowNotification(); 558 } else if (mAlertWindowNotification == null){ 559 mAlertWindowNotification = new AlertWindowNotification(mService, mPackageName); 560 if (mShowingAlertWindowNotificationAllowed) { 561 mAlertWindowNotification.post(); 562 } 563 } 564 } 565 } 566 567 if (type != TYPE_APPLICATION_OVERLAY) { 568 return; 569 } 570 571 if (visible) { 572 changed = mAppOverlaySurfaces.add(surfaceController); 573 MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type, false); 574 } else { 575 changed = mAppOverlaySurfaces.remove(surfaceController); 576 MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type, false); 577 } 578 579 if (changed) { 580 // Notify activity manager of changes to app overlay windows so it can adjust the 581 // importance score for the process. 582 setHasOverlayUi(!mAppOverlaySurfaces.isEmpty()); 583 } 584 } 585 setShowingAlertWindowNotificationAllowed(boolean allowed)586 void setShowingAlertWindowNotificationAllowed(boolean allowed) { 587 mShowingAlertWindowNotificationAllowed = allowed; 588 if (mAlertWindowNotification != null) { 589 if (allowed) { 590 mAlertWindowNotification.post(); 591 } else { 592 mAlertWindowNotification.cancel(false /* deleteChannel */); 593 } 594 } 595 } 596 killSessionLocked()597 private void killSessionLocked() { 598 if (mNumWindow > 0 || !mClientDead) { 599 return; 600 } 601 602 mService.mSessions.remove(this); 603 if (mSurfaceSession == null) { 604 return; 605 } 606 607 if (DEBUG) { 608 Slog.v(TAG_WM, "Last window removed from " + this 609 + ", destroying " + mSurfaceSession); 610 } 611 ProtoLog.i(WM_SHOW_TRANSACTIONS, " KILL SURFACE SESSION %s", mSurfaceSession); 612 try { 613 mSurfaceSession.kill(); 614 } catch (Exception e) { 615 Slog.w(TAG_WM, "Exception thrown when killing surface session " + mSurfaceSession 616 + " in session " + this + ": " + e.toString()); 617 } 618 mSurfaceSession = null; 619 mAlertWindowSurfaces.clear(); 620 mAppOverlaySurfaces.clear(); 621 setHasOverlayUi(false); 622 cancelAlertWindowNotification(); 623 } 624 setHasOverlayUi(boolean hasOverlayUi)625 private void setHasOverlayUi(boolean hasOverlayUi) { 626 mService.mH.obtainMessage(H.SET_HAS_OVERLAY_UI, mPid, hasOverlayUi ? 1 : 0).sendToTarget(); 627 } 628 cancelAlertWindowNotification()629 private void cancelAlertWindowNotification() { 630 if (mAlertWindowNotification == null) { 631 return; 632 } 633 mAlertWindowNotification.cancel(true /* deleteChannel */); 634 mAlertWindowNotification = null; 635 } 636 dump(PrintWriter pw, String prefix)637 void dump(PrintWriter pw, String prefix) { 638 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow); 639 pw.print(" mCanAddInternalSystemWindow="); pw.print(mCanAddInternalSystemWindow); 640 pw.print(" mAppOverlaySurfaces="); pw.print(mAppOverlaySurfaces); 641 pw.print(" mAlertWindowSurfaces="); pw.print(mAlertWindowSurfaces); 642 pw.print(" mClientDead="); pw.print(mClientDead); 643 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession); 644 pw.print(prefix); pw.print("mPackageName="); pw.println(mPackageName); 645 } 646 647 @Override toString()648 public String toString() { 649 return mStringName; 650 } 651 652 /** @return {@code true} if there is an alert window surface on the given display. */ hasAlertWindowSurfaces(DisplayContent displayContent)653 boolean hasAlertWindowSurfaces(DisplayContent displayContent) { 654 for (int i = mAlertWindowSurfaces.size() - 1; i >= 0; i--) { 655 final WindowSurfaceController surfaceController = mAlertWindowSurfaces.valueAt(i); 656 if (surfaceController.mAnimator.mWin.getDisplayContent() == displayContent) { 657 return true; 658 } 659 } 660 return false; 661 } 662 663 @Override grantInputChannel(int displayId, SurfaceControl surface, IWindow window, IBinder hostInputToken, int flags, int type, InputChannel outInputChannel)664 public void grantInputChannel(int displayId, SurfaceControl surface, 665 IWindow window, IBinder hostInputToken, int flags, int type, 666 InputChannel outInputChannel) { 667 if (hostInputToken == null && !mCanAddInternalSystemWindow) { 668 // Callers without INTERNAL_SYSTEM_WINDOW permission cannot grant input channel to 669 // embedded windows without providing a host window input token 670 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 671 } 672 673 if (!mCanAddInternalSystemWindow && type != 0) { 674 Slog.w(TAG_WM, "Requires INTERNAL_SYSTEM_WINDOW permission if assign type to" 675 + " input"); 676 } 677 678 final long identity = Binder.clearCallingIdentity(); 679 try { 680 mService.grantInputChannel(mUid, mPid, displayId, surface, window, hostInputToken, 681 flags, mCanAddInternalSystemWindow ? type : 0, outInputChannel); 682 } finally { 683 Binder.restoreCallingIdentity(identity); 684 } 685 } 686 687 @Override updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface, int flags, Region region)688 public void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface, 689 int flags, Region region) { 690 final long identity = Binder.clearCallingIdentity(); 691 try { 692 mService.updateInputChannel(channelToken, displayId, surface, flags, region); 693 } finally { 694 Binder.restoreCallingIdentity(identity); 695 } 696 } 697 } 698