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