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