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