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