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