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.HIDE_OVERLAY_WINDOWS; 22 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; 23 import static android.Manifest.permission.START_TASKS_FROM_RECENTS; 24 import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY; 25 import static android.app.ActivityTaskManager.INVALID_TASK_ID; 26 import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY; 27 import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; 28 import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK; 29 import static android.content.Intent.EXTRA_PACKAGE_NAME; 30 import static android.content.Intent.EXTRA_SHORTCUT_ID; 31 import static android.content.Intent.EXTRA_TASK_ID; 32 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 33 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 34 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 35 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; 36 37 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; 38 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; 39 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; 40 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 41 42 import android.annotation.Nullable; 43 import android.app.PendingIntent; 44 import android.content.ClipData; 45 import android.content.ClipDescription; 46 import android.content.Intent; 47 import android.content.pm.ActivityInfo; 48 import android.content.pm.ShortcutServiceInternal; 49 import android.graphics.Point; 50 import android.graphics.Rect; 51 import android.graphics.Region; 52 import android.os.Binder; 53 import android.os.Bundle; 54 import android.os.IBinder; 55 import android.os.Parcel; 56 import android.os.Process; 57 import android.os.RemoteCallback; 58 import android.os.RemoteException; 59 import android.os.Trace; 60 import android.os.UserHandle; 61 import android.text.TextUtils; 62 import android.util.ArraySet; 63 import android.util.MergedConfiguration; 64 import android.util.Slog; 65 import android.view.IWindow; 66 import android.view.IWindowId; 67 import android.view.IWindowSession; 68 import android.view.IWindowSessionCallback; 69 import android.view.InputChannel; 70 import android.view.InsetsSourceControl; 71 import android.view.InsetsState; 72 import android.view.SurfaceControl; 73 import android.view.SurfaceSession; 74 import android.view.WindowManager; 75 import android.window.ClientWindowFrames; 76 77 import com.android.internal.annotations.VisibleForTesting; 78 import com.android.internal.os.logging.MetricsLoggerWrapper; 79 import com.android.internal.protolog.common.ProtoLog; 80 import com.android.server.LocalServices; 81 import com.android.server.wm.WindowManagerService.H; 82 83 import java.io.PrintWriter; 84 import java.util.List; 85 import java.util.function.BiConsumer; 86 87 /** 88 * This class represents an active client session. There is generally one 89 * Session object per process that is interacting with the window manager. 90 */ 91 class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { 92 final WindowManagerService mService; 93 final IWindowSessionCallback mCallback; 94 final int mUid; 95 final int mPid; 96 private final String mStringName; 97 SurfaceSession mSurfaceSession; 98 private int mNumWindow = 0; 99 // Set of visible application overlay window surfaces connected to this session. 100 private final ArraySet<WindowSurfaceController> mAppOverlaySurfaces = new ArraySet<>(); 101 // Set of visible alert window surfaces connected to this session. 102 private final ArraySet<WindowSurfaceController> mAlertWindowSurfaces = new ArraySet<>(); 103 private final DragDropController mDragDropController; 104 final boolean mCanAddInternalSystemWindow; 105 private final boolean mCanStartTasksFromRecents; 106 107 final boolean mCanCreateSystemApplicationOverlay; 108 final boolean mCanHideNonSystemOverlayWindows; 109 final boolean mCanAcquireSleepToken; 110 private AlertWindowNotification mAlertWindowNotification; 111 private boolean mShowingAlertWindowNotificationAllowed; 112 private boolean mClientDead = false; 113 private float mLastReportedAnimatorScale; 114 private String mPackageName; 115 private String mRelayoutTag; 116 private final InsetsState mDummyRequestedVisibility = new InsetsState(); 117 private final InsetsSourceControl[] mDummyControls = new InsetsSourceControl[0]; 118 Session(WindowManagerService service, IWindowSessionCallback callback)119 public Session(WindowManagerService service, IWindowSessionCallback callback) { 120 mService = service; 121 mCallback = callback; 122 mUid = Binder.getCallingUid(); 123 mPid = Binder.getCallingPid(); 124 mLastReportedAnimatorScale = service.getCurrentAnimatorScale(); 125 mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission( 126 INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED; 127 mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission( 128 HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED 129 || service.mContext.checkCallingOrSelfPermission(HIDE_OVERLAY_WINDOWS) 130 == PERMISSION_GRANTED; 131 mCanCreateSystemApplicationOverlay = 132 service.mContext.checkCallingOrSelfPermission(SYSTEM_APPLICATION_OVERLAY) 133 == PERMISSION_GRANTED; 134 mCanStartTasksFromRecents = service.mContext.checkCallingOrSelfPermission( 135 START_TASKS_FROM_RECENTS) == PERMISSION_GRANTED; 136 mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER) 137 == PERMISSION_GRANTED; 138 mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications; 139 mDragDropController = mService.mDragDropController; 140 StringBuilder sb = new StringBuilder(); 141 sb.append("Session{"); 142 sb.append(Integer.toHexString(System.identityHashCode(this))); 143 sb.append(" "); 144 sb.append(mPid); 145 if (mUid < Process.FIRST_APPLICATION_UID) { 146 sb.append(":"); 147 sb.append(mUid); 148 } else { 149 sb.append(":u"); 150 sb.append(UserHandle.getUserId(mUid)); 151 sb.append('a'); 152 sb.append(UserHandle.getAppId(mUid)); 153 } 154 sb.append("}"); 155 mStringName = sb.toString(); 156 157 try { 158 mCallback.asBinder().linkToDeath(this, 0); 159 } catch (RemoteException e) { 160 // The caller has died, so we can just forget about this. 161 // Hmmm, should we call killSessionLocked()?? 162 } 163 } 164 165 @Override onTransact(int code, Parcel data, Parcel reply, int flags)166 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 167 throws RemoteException { 168 try { 169 return super.onTransact(code, data, reply, flags); 170 } catch (RuntimeException e) { 171 // Log all 'real' exceptions thrown to the caller 172 if (!(e instanceof SecurityException)) { 173 Slog.wtf(TAG_WM, "Window Session Crash", e); 174 } 175 throw e; 176 } 177 } 178 179 @Override binderDied()180 public void binderDied() { 181 synchronized (mService.mGlobalLock) { 182 mCallback.asBinder().unlinkToDeath(this, 0); 183 mClientDead = true; 184 killSessionLocked(); 185 } 186 } 187 188 @Override addToDisplay(IWindow window, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, InsetsState requestedVisibility, InputChannel outInputChannel, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls)189 public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs, 190 int viewVisibility, int displayId, InsetsState requestedVisibility, 191 InputChannel outInputChannel, InsetsState outInsetsState, 192 InsetsSourceControl[] outActiveControls) { 193 return mService.addWindow(this, window, attrs, viewVisibility, displayId, 194 UserHandle.getUserId(mUid), requestedVisibility, outInputChannel, outInsetsState, 195 outActiveControls); 196 } 197 198 199 @Override addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, int userId, InsetsState requestedVisibility, InputChannel outInputChannel, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls)200 public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs, 201 int viewVisibility, int displayId, int userId, InsetsState requestedVisibility, 202 InputChannel outInputChannel, InsetsState outInsetsState, 203 InsetsSourceControl[] outActiveControls) { 204 return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId, 205 requestedVisibility, outInputChannel, outInsetsState, outActiveControls); 206 } 207 208 @Override addToDisplayWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, InsetsState outInsetsState)209 public int addToDisplayWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs, 210 int viewVisibility, int displayId, InsetsState outInsetsState) { 211 return mService.addWindow(this, window, attrs, viewVisibility, displayId, 212 UserHandle.getUserId(mUid), mDummyRequestedVisibility, null /* outInputChannel */, 213 outInsetsState, mDummyControls); 214 } 215 216 @Override remove(IWindow window)217 public void remove(IWindow window) { 218 mService.removeWindow(this, window); 219 } 220 221 @Override prepareToReplaceWindows(IBinder appToken, boolean childrenOnly)222 public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) { 223 mService.setWillReplaceWindows(appToken, childrenOnly); 224 } 225 226 @Override relayout(IWindow window, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls, Point outSurfaceSize)227 public int relayout(IWindow window, WindowManager.LayoutParams attrs, 228 int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber, 229 ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, 230 SurfaceControl outSurfaceControl, InsetsState outInsetsState, 231 InsetsSourceControl[] outActiveControls, Point outSurfaceSize) { 232 if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from " 233 + Binder.getCallingPid()); 234 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag); 235 int res = mService.relayoutWindow(this, window, attrs, 236 requestedWidth, requestedHeight, viewFlags, flags, frameNumber, 237 outFrames, mergedConfiguration, outSurfaceControl, outInsetsState, 238 outActiveControls, outSurfaceSize); 239 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 240 if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to " 241 + Binder.getCallingPid()); 242 return res; 243 } 244 245 @Override outOfMemory(IWindow window)246 public boolean outOfMemory(IWindow window) { 247 return mService.outOfMemoryWindow(this, window); 248 } 249 250 @Override setInsets(IWindow window, int touchableInsets, Rect contentInsets, Rect visibleInsets, Region touchableArea)251 public void setInsets(IWindow window, int touchableInsets, 252 Rect contentInsets, Rect visibleInsets, Region touchableArea) { 253 mService.setInsetsWindow(this, window, touchableInsets, contentInsets, 254 visibleInsets, touchableArea); 255 } 256 257 @Override finishDrawing(IWindow window, @Nullable SurfaceControl.Transaction postDrawTransaction)258 public void finishDrawing(IWindow window, 259 @Nullable SurfaceControl.Transaction postDrawTransaction) { 260 if (DEBUG) Slog.v(TAG_WM, "IWindow finishDrawing called for " + window); 261 mService.finishDrawingWindow(this, window, postDrawTransaction); 262 } 263 264 @Override setInTouchMode(boolean mode)265 public void setInTouchMode(boolean mode) { 266 mService.setInTouchMode(mode); 267 } 268 269 @Override getInTouchMode()270 public boolean getInTouchMode() { 271 return mService.getInTouchMode(); 272 } 273 274 @Override performHapticFeedback(int effectId, boolean always)275 public boolean performHapticFeedback(int effectId, boolean always) { 276 final long ident = Binder.clearCallingIdentity(); 277 try { 278 return mService.mPolicy.performHapticFeedback(mUid, mPackageName, 279 effectId, always, null); 280 } finally { 281 Binder.restoreCallingIdentity(ident); 282 } 283 } 284 285 /* Drag/drop */ 286 287 @Override performDrag(IWindow window, int flags, SurfaceControl surface, int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data)288 public IBinder performDrag(IWindow window, int flags, SurfaceControl surface, int touchSource, 289 float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data) { 290 // Validate and resolve ClipDescription data before clearing the calling identity 291 validateAndResolveDragMimeTypeExtras(data, Binder.getCallingUid(), Binder.getCallingPid(), 292 mPackageName); 293 final long ident = Binder.clearCallingIdentity(); 294 try { 295 return mDragDropController.performDrag(mPid, mUid, window, flags, surface, touchSource, 296 touchX, touchY, thumbCenterX, thumbCenterY, data); 297 } finally { 298 Binder.restoreCallingIdentity(ident); 299 } 300 } 301 302 /** 303 * Validates the given drag data. 304 */ 305 @VisibleForTesting validateAndResolveDragMimeTypeExtras(ClipData data, int callingUid, int callingPid, String callingPackage)306 void validateAndResolveDragMimeTypeExtras(ClipData data, int callingUid, int callingPid, 307 String callingPackage) { 308 if (callingUid == Process.SYSTEM_UID) { 309 throw new IllegalStateException("Need to validate before calling identify is cleared"); 310 } 311 final ClipDescription desc = data != null ? data.getDescription() : null; 312 if (desc == null) { 313 return; 314 } 315 // Ensure that only one of the app mime types are set 316 final boolean hasActivity = desc.hasMimeType(MIMETYPE_APPLICATION_ACTIVITY); 317 final boolean hasShortcut = desc.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT); 318 final boolean hasTask = desc.hasMimeType(MIMETYPE_APPLICATION_TASK); 319 int appMimeTypeCount = (hasActivity ? 1 : 0) 320 + (hasShortcut ? 1 : 0) 321 + (hasTask ? 1 : 0); 322 if (appMimeTypeCount == 0) { 323 return; 324 } else if (appMimeTypeCount > 1) { 325 throw new IllegalArgumentException("Can not specify more than one of activity, " 326 + "shortcut, or task mime types"); 327 } 328 // Ensure that data is provided and that they are intents 329 if (data.getItemCount() == 0) { 330 throw new IllegalArgumentException("Unexpected number of items (none)"); 331 } 332 for (int i = 0; i < data.getItemCount(); i++) { 333 if (data.getItemAt(i).getIntent() == null) { 334 throw new IllegalArgumentException("Unexpected item, expected an intent"); 335 } 336 } 337 338 if (hasActivity) { 339 long origId = Binder.clearCallingIdentity(); 340 try { 341 // Resolve the activity info for each intent 342 for (int i = 0; i < data.getItemCount(); i++) { 343 final ClipData.Item item = data.getItemAt(i); 344 final Intent intent = item.getIntent(); 345 final PendingIntent pi = intent.getParcelableExtra( 346 ClipDescription.EXTRA_PENDING_INTENT); 347 final UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER); 348 if (pi == null || user == null) { 349 throw new IllegalArgumentException("Clip data must include the pending " 350 + "intent to launch and its associated user to launch for."); 351 } 352 final Intent launchIntent = mService.mAmInternal.getIntentForIntentSender( 353 pi.getIntentSender().getTarget()); 354 final ActivityInfo info = mService.mAtmService.resolveActivityInfoForIntent( 355 launchIntent, null /* resolvedType */, user.getIdentifier(), 356 callingUid); 357 item.setActivityInfo(info); 358 } 359 } finally { 360 Binder.restoreCallingIdentity(origId); 361 } 362 } else if (hasShortcut) { 363 // Restrict who can start a shortcut drag since it will start the shortcut as the 364 // target shortcut package 365 if (!mCanStartTasksFromRecents) { 366 throw new SecurityException("Requires START_TASKS_FROM_RECENTS permission"); 367 } 368 for (int i = 0; i < data.getItemCount(); i++) { 369 final ClipData.Item item = data.getItemAt(i); 370 final Intent intent = item.getIntent(); 371 final String shortcutId = intent.getStringExtra(EXTRA_SHORTCUT_ID); 372 final String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME); 373 final UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER); 374 if (TextUtils.isEmpty(shortcutId) 375 || TextUtils.isEmpty(packageName) 376 || user == null) { 377 throw new IllegalArgumentException("Clip item must include the package name, " 378 + "shortcut id, and the user to launch for."); 379 } 380 final ShortcutServiceInternal shortcutService = 381 LocalServices.getService(ShortcutServiceInternal.class); 382 final Intent[] shortcutIntents = shortcutService.createShortcutIntents( 383 callingUid, callingPackage, packageName, shortcutId, 384 user.getIdentifier(), callingPid, callingUid); 385 if (shortcutIntents == null || shortcutIntents.length == 0) { 386 throw new IllegalArgumentException("Invalid shortcut id"); 387 } 388 final ActivityInfo info = mService.mAtmService.resolveActivityInfoForIntent( 389 shortcutIntents[0], null /* resolvedType */, user.getIdentifier(), 390 callingUid); 391 item.setActivityInfo(info); 392 } 393 } else if (hasTask) { 394 // TODO(b/169894807): Consider opening this up for tasks from the same app as the caller 395 if (!mCanStartTasksFromRecents) { 396 throw new SecurityException("Requires START_TASKS_FROM_RECENTS permission"); 397 } 398 for (int i = 0; i < data.getItemCount(); i++) { 399 final ClipData.Item item = data.getItemAt(i); 400 final Intent intent = item.getIntent(); 401 final int taskId = intent.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID); 402 if (taskId == INVALID_TASK_ID) { 403 throw new IllegalArgumentException("Clip item must include the task id."); 404 } 405 final Task task = mService.mRoot.anyTaskForId(taskId); 406 if (task == null) { 407 throw new IllegalArgumentException("Invalid task id."); 408 } 409 if (task.getRootActivity() != null) { 410 item.setActivityInfo(task.getRootActivity().info); 411 } else { 412 // Resolve the activity info manually if the task was restored after reboot 413 final ActivityInfo info = mService.mAtmService.resolveActivityInfoForIntent( 414 task.intent, null /* resolvedType */, task.mUserId, callingUid); 415 item.setActivityInfo(info); 416 } 417 } 418 } 419 } 420 421 @Override reportDropResult(IWindow window, boolean consumed)422 public void reportDropResult(IWindow window, boolean consumed) { 423 final long ident = Binder.clearCallingIdentity(); 424 try { 425 mDragDropController.reportDropResult(window, consumed); 426 } finally { 427 Binder.restoreCallingIdentity(ident); 428 } 429 } 430 431 @Override cancelDragAndDrop(IBinder dragToken, boolean skipAnimation)432 public void cancelDragAndDrop(IBinder dragToken, boolean skipAnimation) { 433 final long ident = Binder.clearCallingIdentity(); 434 try { 435 mDragDropController.cancelDragAndDrop(dragToken, skipAnimation); 436 } finally { 437 Binder.restoreCallingIdentity(ident); 438 } 439 } 440 441 @Override dragRecipientEntered(IWindow window)442 public void dragRecipientEntered(IWindow window) { 443 mDragDropController.dragRecipientEntered(window); 444 } 445 446 @Override dragRecipientExited(IWindow window)447 public void dragRecipientExited(IWindow window) { 448 mDragDropController.dragRecipientExited(window); 449 } 450 451 @Override startMovingTask(IWindow window, float startX, float startY)452 public boolean startMovingTask(IWindow window, float startX, float startY) { 453 if (DEBUG_TASK_POSITIONING) Slog.d( 454 TAG_WM, "startMovingTask: {" + startX + "," + startY + "}"); 455 456 final long ident = Binder.clearCallingIdentity(); 457 try { 458 return mService.mTaskPositioningController.startMovingTask(window, startX, startY); 459 } finally { 460 Binder.restoreCallingIdentity(ident); 461 } 462 } 463 464 @Override finishMovingTask(IWindow window)465 public void finishMovingTask(IWindow window) { 466 if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "finishMovingTask"); 467 468 final long ident = Binder.clearCallingIdentity(); 469 try { 470 mService.mTaskPositioningController.finishTaskPositioning(window); 471 } finally { 472 Binder.restoreCallingIdentity(ident); 473 } 474 } 475 476 @Override reportSystemGestureExclusionChanged(IWindow window, List<Rect> exclusionRects)477 public void reportSystemGestureExclusionChanged(IWindow window, List<Rect> exclusionRects) { 478 final long ident = Binder.clearCallingIdentity(); 479 try { 480 mService.reportSystemGestureExclusionChanged(this, window, exclusionRects); 481 } finally { 482 Binder.restoreCallingIdentity(ident); 483 } 484 } 485 actionOnWallpaper(IBinder window, BiConsumer<WallpaperController, WindowState> action)486 private void actionOnWallpaper(IBinder window, 487 BiConsumer<WallpaperController, WindowState> action) { 488 final WindowState windowState = mService.windowForClientLocked(this, window, true); 489 action.accept(windowState.getDisplayContent().mWallpaperController, windowState); 490 } 491 492 @Override setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep)493 public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) { 494 synchronized (mService.mGlobalLock) { 495 final long ident = Binder.clearCallingIdentity(); 496 try { 497 actionOnWallpaper(window, (wpController, windowState) -> 498 wpController.setWindowWallpaperPosition(windowState, x, y, xStep, yStep)); 499 } finally { 500 Binder.restoreCallingIdentity(ident); 501 } 502 } 503 } 504 505 @Override setWallpaperZoomOut(IBinder window, float zoom)506 public void setWallpaperZoomOut(IBinder window, float zoom) { 507 if (Float.compare(0f, zoom) > 0 || Float.compare(1f, zoom) < 0 || Float.isNaN(zoom)) { 508 throw new IllegalArgumentException("Zoom must be a valid float between 0 and 1: " 509 + zoom); 510 } 511 synchronized (mService.mGlobalLock) { 512 final long ident = Binder.clearCallingIdentity(); 513 try { 514 actionOnWallpaper(window, (wpController, windowState) -> 515 wpController.setWallpaperZoomOut(windowState, zoom)); 516 } finally { 517 Binder.restoreCallingIdentity(ident); 518 } 519 } 520 } 521 522 @Override setShouldZoomOutWallpaper(IBinder window, boolean shouldZoom)523 public void setShouldZoomOutWallpaper(IBinder window, boolean shouldZoom) { 524 synchronized (mService.mGlobalLock) { 525 actionOnWallpaper(window, (wpController, windowState) -> 526 wpController.setShouldZoomOutWallpaper(windowState, shouldZoom)); 527 } 528 } 529 530 @Override wallpaperOffsetsComplete(IBinder window)531 public void wallpaperOffsetsComplete(IBinder window) { 532 synchronized (mService.mGlobalLock) { 533 actionOnWallpaper(window, (wpController, windowState) -> 534 wpController.wallpaperOffsetsComplete(window)); 535 } 536 } 537 538 @Override setWallpaperDisplayOffset(IBinder window, int x, int y)539 public void setWallpaperDisplayOffset(IBinder window, int x, int y) { 540 synchronized (mService.mGlobalLock) { 541 final long ident = Binder.clearCallingIdentity(); 542 try { 543 actionOnWallpaper(window, (wpController, windowState) -> 544 wpController.setWindowWallpaperDisplayOffset(windowState, x, y)); 545 } finally { 546 Binder.restoreCallingIdentity(ident); 547 } 548 } 549 } 550 551 @Override sendWallpaperCommand(IBinder window, String action, int x, int y, int z, Bundle extras, boolean sync)552 public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y, 553 int z, Bundle extras, boolean sync) { 554 synchronized (mService.mGlobalLock) { 555 final long ident = Binder.clearCallingIdentity(); 556 try { 557 final WindowState windowState = mService.windowForClientLocked(this, window, true); 558 return windowState.getDisplayContent().mWallpaperController 559 .sendWindowWallpaperCommand(windowState, action, x, y, z, extras, sync); 560 } finally { 561 Binder.restoreCallingIdentity(ident); 562 } 563 } 564 } 565 566 @Override wallpaperCommandComplete(IBinder window, Bundle result)567 public void wallpaperCommandComplete(IBinder window, Bundle result) { 568 synchronized (mService.mGlobalLock) { 569 actionOnWallpaper(window, (wpController, windowState) -> 570 wpController.wallpaperCommandComplete(window)); 571 } 572 } 573 574 @Override onRectangleOnScreenRequested(IBinder token, Rect rectangle)575 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { 576 synchronized (mService.mGlobalLock) { 577 final long identity = Binder.clearCallingIdentity(); 578 try { 579 mService.onRectangleOnScreenRequested(token, rectangle); 580 } finally { 581 Binder.restoreCallingIdentity(identity); 582 } 583 } 584 } 585 586 @Override getWindowId(IBinder window)587 public IWindowId getWindowId(IBinder window) { 588 return mService.getWindowId(window); 589 } 590 591 @Override pokeDrawLock(IBinder window)592 public void pokeDrawLock(IBinder window) { 593 final long identity = Binder.clearCallingIdentity(); 594 try { 595 mService.pokeDrawLock(this, window); 596 } finally { 597 Binder.restoreCallingIdentity(identity); 598 } 599 } 600 601 @Override updatePointerIcon(IWindow window)602 public void updatePointerIcon(IWindow window) { 603 final long identity = Binder.clearCallingIdentity(); 604 try { 605 mService.updatePointerIcon(window); 606 } finally { 607 Binder.restoreCallingIdentity(identity); 608 } 609 } 610 611 @Override updateDisplayContentLocation(IWindow window, int x, int y, int displayId)612 public void updateDisplayContentLocation(IWindow window, int x, int y, int displayId) { 613 mService.updateDisplayContentLocation(window, x, y, displayId); 614 } 615 616 @Override updateTapExcludeRegion(IWindow window, Region region)617 public void updateTapExcludeRegion(IWindow window, Region region) { 618 final long identity = Binder.clearCallingIdentity(); 619 try { 620 mService.updateTapExcludeRegion(window, region); 621 } finally { 622 Binder.restoreCallingIdentity(identity); 623 } 624 } 625 626 @Override insetsModified(IWindow window, InsetsState state)627 public void insetsModified(IWindow window, InsetsState state) { 628 synchronized (mService.mGlobalLock) { 629 final WindowState windowState = mService.windowForClientLocked(this, window, 630 false /* throwOnError */); 631 if (windowState != null) { 632 windowState.updateRequestedVisibility(state); 633 windowState.getDisplayContent().getInsetsPolicy().onInsetsModified(windowState); 634 } 635 } 636 } 637 windowAddedLocked()638 void windowAddedLocked() { 639 if (mPackageName == null) { 640 final WindowProcessController wpc = mService.mAtmService.mProcessMap.getProcess(mPid); 641 if (wpc != null) { 642 mPackageName = wpc.mInfo.packageName; 643 mRelayoutTag = "relayoutWindow: " + mPackageName; 644 } else { 645 Slog.e(TAG_WM, "Unknown process pid=" + mPid); 646 } 647 } 648 if (mSurfaceSession == null) { 649 if (DEBUG) { 650 Slog.v(TAG_WM, "First window added to " + this + ", creating SurfaceSession"); 651 } 652 mSurfaceSession = new SurfaceSession(); 653 ProtoLog.i(WM_SHOW_TRANSACTIONS, " NEW SURFACE SESSION %s", mSurfaceSession); 654 mService.mSessions.add(this); 655 if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) { 656 mService.dispatchNewAnimatorScaleLocked(this); 657 } 658 } 659 mNumWindow++; 660 } 661 windowRemovedLocked()662 void windowRemovedLocked() { 663 mNumWindow--; 664 killSessionLocked(); 665 } 666 667 onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController, boolean visible, int type)668 void onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController, 669 boolean visible, int type) { 670 671 if (!isSystemAlertWindowType(type)) { 672 return; 673 } 674 675 boolean changed; 676 677 if (!mCanAddInternalSystemWindow && !mCanCreateSystemApplicationOverlay) { 678 // We want to track non-system apps adding alert windows so we can post an 679 // on-going notification for the user to control their visibility. 680 if (visible) { 681 changed = mAlertWindowSurfaces.add(surfaceController); 682 MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type, true); 683 } else { 684 changed = mAlertWindowSurfaces.remove(surfaceController); 685 MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type, true); 686 } 687 688 if (changed) { 689 if (mAlertWindowSurfaces.isEmpty()) { 690 cancelAlertWindowNotification(); 691 } else if (mAlertWindowNotification == null){ 692 mAlertWindowNotification = new AlertWindowNotification(mService, mPackageName); 693 if (mShowingAlertWindowNotificationAllowed) { 694 mAlertWindowNotification.post(); 695 } 696 } 697 } 698 } 699 700 if (type != TYPE_APPLICATION_OVERLAY) { 701 return; 702 } 703 704 if (visible) { 705 changed = mAppOverlaySurfaces.add(surfaceController); 706 MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type, false); 707 } else { 708 changed = mAppOverlaySurfaces.remove(surfaceController); 709 MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type, false); 710 } 711 712 if (changed) { 713 // Notify activity manager of changes to app overlay windows so it can adjust the 714 // importance score for the process. 715 setHasOverlayUi(!mAppOverlaySurfaces.isEmpty()); 716 } 717 } 718 setShowingAlertWindowNotificationAllowed(boolean allowed)719 void setShowingAlertWindowNotificationAllowed(boolean allowed) { 720 mShowingAlertWindowNotificationAllowed = allowed; 721 if (mAlertWindowNotification != null) { 722 if (allowed) { 723 mAlertWindowNotification.post(); 724 } else { 725 mAlertWindowNotification.cancel(false /* deleteChannel */); 726 } 727 } 728 } 729 killSessionLocked()730 private void killSessionLocked() { 731 if (mNumWindow > 0 || !mClientDead) { 732 return; 733 } 734 735 mService.mSessions.remove(this); 736 if (mSurfaceSession == null) { 737 return; 738 } 739 740 if (DEBUG) { 741 Slog.v(TAG_WM, "Last window removed from " + this 742 + ", destroying " + mSurfaceSession); 743 } 744 ProtoLog.i(WM_SHOW_TRANSACTIONS, " KILL SURFACE SESSION %s", mSurfaceSession); 745 try { 746 mSurfaceSession.kill(); 747 } catch (Exception e) { 748 Slog.w(TAG_WM, "Exception thrown when killing surface session " + mSurfaceSession 749 + " in session " + this + ": " + e.toString()); 750 } 751 mSurfaceSession = null; 752 mAlertWindowSurfaces.clear(); 753 mAppOverlaySurfaces.clear(); 754 setHasOverlayUi(false); 755 cancelAlertWindowNotification(); 756 } 757 setHasOverlayUi(boolean hasOverlayUi)758 private void setHasOverlayUi(boolean hasOverlayUi) { 759 mService.mH.obtainMessage(H.SET_HAS_OVERLAY_UI, mPid, hasOverlayUi ? 1 : 0).sendToTarget(); 760 } 761 cancelAlertWindowNotification()762 private void cancelAlertWindowNotification() { 763 if (mAlertWindowNotification == null) { 764 return; 765 } 766 mAlertWindowNotification.cancel(true /* deleteChannel */); 767 mAlertWindowNotification = null; 768 } 769 dump(PrintWriter pw, String prefix)770 void dump(PrintWriter pw, String prefix) { 771 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow); 772 pw.print(" mCanAddInternalSystemWindow="); pw.print(mCanAddInternalSystemWindow); 773 pw.print(" mAppOverlaySurfaces="); pw.print(mAppOverlaySurfaces); 774 pw.print(" mAlertWindowSurfaces="); pw.print(mAlertWindowSurfaces); 775 pw.print(" mClientDead="); pw.print(mClientDead); 776 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession); 777 pw.print(prefix); pw.print("mPackageName="); pw.println(mPackageName); 778 } 779 780 @Override toString()781 public String toString() { 782 return mStringName; 783 } 784 785 /** @return {@code true} if there is an alert window surface on the given display. */ hasAlertWindowSurfaces(DisplayContent displayContent)786 boolean hasAlertWindowSurfaces(DisplayContent displayContent) { 787 for (int i = mAlertWindowSurfaces.size() - 1; i >= 0; i--) { 788 final WindowSurfaceController surfaceController = mAlertWindowSurfaces.valueAt(i); 789 if (surfaceController.mAnimator.mWin.getDisplayContent() == displayContent) { 790 return true; 791 } 792 } 793 return false; 794 } 795 796 @Override grantInputChannel(int displayId, SurfaceControl surface, IWindow window, IBinder hostInputToken, int flags, int privateFlags, int type, InputChannel outInputChannel)797 public void grantInputChannel(int displayId, SurfaceControl surface, 798 IWindow window, IBinder hostInputToken, int flags, int privateFlags, int type, 799 InputChannel outInputChannel) { 800 if (hostInputToken == null && !mCanAddInternalSystemWindow) { 801 // Callers without INTERNAL_SYSTEM_WINDOW permission cannot grant input channel to 802 // embedded windows without providing a host window input token 803 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 804 } 805 806 if (!mCanAddInternalSystemWindow && type != 0) { 807 Slog.w(TAG_WM, "Requires INTERNAL_SYSTEM_WINDOW permission if assign type to" 808 + " input"); 809 } 810 811 final long identity = Binder.clearCallingIdentity(); 812 try { 813 mService.grantInputChannel(this, mUid, mPid, displayId, surface, window, hostInputToken, 814 flags, mCanAddInternalSystemWindow ? privateFlags : 0, 815 mCanAddInternalSystemWindow ? type : 0, outInputChannel); 816 } finally { 817 Binder.restoreCallingIdentity(identity); 818 } 819 } 820 821 @Override updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface, int flags, int privateFlags, Region region)822 public void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface, 823 int flags, int privateFlags, Region region) { 824 final long identity = Binder.clearCallingIdentity(); 825 try { 826 mService.updateInputChannel(channelToken, displayId, surface, flags, 827 mCanAddInternalSystemWindow ? privateFlags : 0, region); 828 } finally { 829 Binder.restoreCallingIdentity(identity); 830 } 831 } 832 833 @Override grantEmbeddedWindowFocus(IWindow callingWindow, IBinder targetInputToken, boolean grantFocus)834 public void grantEmbeddedWindowFocus(IWindow callingWindow, IBinder targetInputToken, 835 boolean grantFocus) { 836 final long identity = Binder.clearCallingIdentity(); 837 try { 838 if (callingWindow == null) { 839 if (!mCanAddInternalSystemWindow) { 840 // Callers without INTERNAL_SYSTEM_WINDOW permission cannot request focus on 841 // embedded windows without providing the calling window 842 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 843 } 844 mService.grantEmbeddedWindowFocus(this, targetInputToken, grantFocus); 845 } else { 846 mService.grantEmbeddedWindowFocus(this, callingWindow, targetInputToken, 847 grantFocus); 848 } 849 } finally { 850 Binder.restoreCallingIdentity(identity); 851 } 852 } 853 854 @Override generateDisplayHash(IWindow window, Rect boundsInWindow, String hashAlgorithm, RemoteCallback callback)855 public void generateDisplayHash(IWindow window, Rect boundsInWindow, String hashAlgorithm, 856 RemoteCallback callback) { 857 final long origId = Binder.clearCallingIdentity(); 858 try { 859 mService.generateDisplayHash(this, window, boundsInWindow, hashAlgorithm, callback); 860 } finally { 861 Binder.restoreCallingIdentity(origId); 862 } 863 } 864 } 865