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