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