• 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.INTERNAL_SYSTEM_WINDOW;
22 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
23 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
24 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
25 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
26 
27 import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
28 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
29 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
30 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
31 
32 import android.annotation.Nullable;
33 import android.content.ClipData;
34 import android.graphics.Point;
35 import android.graphics.Rect;
36 import android.graphics.Region;
37 import android.os.Binder;
38 import android.os.Bundle;
39 import android.os.IBinder;
40 import android.os.Parcel;
41 import android.os.Process;
42 import android.os.RemoteException;
43 import android.os.Trace;
44 import android.os.UserHandle;
45 import android.util.ArraySet;
46 import android.util.MergedConfiguration;
47 import android.util.Slog;
48 import android.view.DisplayCutout;
49 import android.view.IWindow;
50 import android.view.IWindowId;
51 import android.view.IWindowSession;
52 import android.view.IWindowSessionCallback;
53 import android.view.InputChannel;
54 import android.view.InsetsSourceControl;
55 import android.view.InsetsState;
56 import android.view.SurfaceControl;
57 import android.view.SurfaceSession;
58 import android.view.WindowManager;
59 
60 import com.android.internal.os.logging.MetricsLoggerWrapper;
61 import com.android.server.protolog.common.ProtoLog;
62 import com.android.server.wm.WindowManagerService.H;
63 
64 import java.io.PrintWriter;
65 import java.util.List;
66 import java.util.function.BiConsumer;
67 
68 /**
69  * This class represents an active client session.  There is generally one
70  * Session object per process that is interacting with the window manager.
71  */
72 class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
73     final WindowManagerService mService;
74     final IWindowSessionCallback mCallback;
75     final int mUid;
76     final int mPid;
77     private final String mStringName;
78     SurfaceSession mSurfaceSession;
79     private int mNumWindow = 0;
80     // Set of visible application overlay window surfaces connected to this session.
81     private final ArraySet<WindowSurfaceController> mAppOverlaySurfaces = new ArraySet<>();
82     // Set of visible alert window surfaces connected to this session.
83     private final ArraySet<WindowSurfaceController> mAlertWindowSurfaces = new ArraySet<>();
84     private final DragDropController mDragDropController;
85     final boolean mCanAddInternalSystemWindow;
86     final boolean mCanHideNonSystemOverlayWindows;
87     final boolean mCanAcquireSleepToken;
88     private AlertWindowNotification mAlertWindowNotification;
89     private boolean mShowingAlertWindowNotificationAllowed;
90     private boolean mClientDead = false;
91     private float mLastReportedAnimatorScale;
92     private String mPackageName;
93     private String mRelayoutTag;
94     private final InsetsSourceControl[] mDummyControls =  new InsetsSourceControl[0];
95 
Session(WindowManagerService service, IWindowSessionCallback callback)96     public Session(WindowManagerService service, IWindowSessionCallback callback) {
97         mService = service;
98         mCallback = callback;
99         mUid = Binder.getCallingUid();
100         mPid = Binder.getCallingPid();
101         mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
102         mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission(
103                 INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
104         mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission(
105                 HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED;
106         mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER)
107                 == PERMISSION_GRANTED;
108         mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
109         mDragDropController = mService.mDragDropController;
110         StringBuilder sb = new StringBuilder();
111         sb.append("Session{");
112         sb.append(Integer.toHexString(System.identityHashCode(this)));
113         sb.append(" ");
114         sb.append(mPid);
115         if (mUid < Process.FIRST_APPLICATION_UID) {
116             sb.append(":");
117             sb.append(mUid);
118         } else {
119             sb.append(":u");
120             sb.append(UserHandle.getUserId(mUid));
121             sb.append('a');
122             sb.append(UserHandle.getAppId(mUid));
123         }
124         sb.append("}");
125         mStringName = sb.toString();
126 
127         try {
128             mCallback.asBinder().linkToDeath(this, 0);
129         } catch (RemoteException e) {
130             // The caller has died, so we can just forget about this.
131             // Hmmm, should we call killSessionLocked()??
132         }
133     }
134 
135     @Override
onTransact(int code, Parcel data, Parcel reply, int flags)136     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
137             throws RemoteException {
138         try {
139             return super.onTransact(code, data, reply, flags);
140         } catch (RuntimeException e) {
141             // Log all 'real' exceptions thrown to the caller
142             if (!(e instanceof SecurityException)) {
143                 Slog.wtf(TAG_WM, "Window Session Crash", e);
144             }
145             throw e;
146         }
147     }
148 
149     @Override
binderDied()150     public void binderDied() {
151         synchronized (mService.mGlobalLock) {
152             mCallback.asBinder().unlinkToDeath(this, 0);
153             mClientDead = true;
154             killSessionLocked();
155         }
156     }
157 
158     @Override
addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets, Rect outStableInsets, DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls)159     public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
160             int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
161             Rect outStableInsets,
162             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
163             InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
164         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
165                 outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
166                 outInsetsState, outActiveControls, UserHandle.getUserId(mUid));
167     }
168 
169 
170     @Override
addToDisplayAsUser(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, int userId, Rect outFrame, Rect outContentInsets, Rect outStableInsets, DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls)171     public int addToDisplayAsUser(IWindow window, int seq, WindowManager.LayoutParams attrs,
172             int viewVisibility, int displayId, int userId, Rect outFrame,
173             Rect outContentInsets, Rect outStableInsets,
174             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
175             InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
176         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
177                 outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
178                 outInsetsState, outActiveControls, userId);
179     }
180 
181     @Override
addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, InsetsState outInsetsState)182     public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
183             int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
184             InsetsState outInsetsState) {
185         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
186                 new Rect() /* outFrame */, outContentInsets, outStableInsets,
187                 new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */,
188                 outInsetsState, mDummyControls, UserHandle.getUserId(mUid));
189     }
190 
191     @Override
remove(IWindow window)192     public void remove(IWindow window) {
193         mService.removeWindow(this, window);
194     }
195 
196     @Override
prepareToReplaceWindows(IBinder appToken, boolean childrenOnly)197     public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) {
198         mService.setWillReplaceWindows(appToken, childrenOnly);
199     }
200 
201     @Override
relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber, Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outBackdropFrame, DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls, Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl)202     public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
203             int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
204             Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
205             Rect outStableInsets, Rect outBackdropFrame,
206             DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
207             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
208             InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
209             SurfaceControl outBLASTSurfaceControl) {
210         if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
211                 + Binder.getCallingPid());
212         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
213         int res = mService.relayoutWindow(this, window, seq, attrs,
214                 requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
215                 outFrame, outContentInsets, outVisibleInsets,
216                 outStableInsets, outBackdropFrame, cutout,
217                 mergedConfiguration, outSurfaceControl, outInsetsState, outActiveControls,
218                 outSurfaceSize, outBLASTSurfaceControl);
219         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
220         if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
221                 + Binder.getCallingPid());
222         return res;
223     }
224 
225     @Override
outOfMemory(IWindow window)226     public boolean outOfMemory(IWindow window) {
227         return mService.outOfMemoryWindow(this, window);
228     }
229 
230     @Override
setTransparentRegion(IWindow window, Region region)231     public void setTransparentRegion(IWindow window, Region region) {
232         mService.setTransparentRegionWindow(this, window, region);
233     }
234 
235     @Override
setInsets(IWindow window, int touchableInsets, Rect contentInsets, Rect visibleInsets, Region touchableArea)236     public void setInsets(IWindow window, int touchableInsets,
237             Rect contentInsets, Rect visibleInsets, Region touchableArea) {
238         mService.setInsetsWindow(this, window, touchableInsets, contentInsets,
239                 visibleInsets, touchableArea);
240     }
241 
242     @Override
getDisplayFrame(IWindow window, Rect outDisplayFrame)243     public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
244         mService.getWindowDisplayFrame(this, window, outDisplayFrame);
245     }
246 
247     @Override
finishDrawing(IWindow window, @Nullable SurfaceControl.Transaction postDrawTransaction)248     public void finishDrawing(IWindow window,
249             @Nullable SurfaceControl.Transaction postDrawTransaction) {
250         if (DEBUG) Slog.v(TAG_WM, "IWindow finishDrawing called for " + window);
251         mService.finishDrawingWindow(this, window, postDrawTransaction);
252     }
253 
254     @Override
setInTouchMode(boolean mode)255     public void setInTouchMode(boolean mode) {
256         mService.setInTouchMode(mode);
257     }
258 
259     @Override
getInTouchMode()260     public boolean getInTouchMode() {
261         return mService.getInTouchMode();
262     }
263 
264     @Override
performHapticFeedback(int effectId, boolean always)265     public boolean performHapticFeedback(int effectId, boolean always) {
266         long ident = Binder.clearCallingIdentity();
267         try {
268             return mService.mPolicy.performHapticFeedback(mUid, mPackageName,
269                         effectId, always, null);
270         } finally {
271             Binder.restoreCallingIdentity(ident);
272         }
273     }
274 
275     /* Drag/drop */
276 
277     @Override
performDrag(IWindow window, int flags, SurfaceControl surface, int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data)278     public IBinder performDrag(IWindow window, int flags, SurfaceControl surface, int touchSource,
279             float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data) {
280         final long ident = Binder.clearCallingIdentity();
281         try {
282             return mDragDropController.performDrag(mSurfaceSession, mPid, mUid, window,
283                     flags, surface, touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data);
284         } finally {
285             Binder.restoreCallingIdentity(ident);
286         }
287     }
288 
289     @Override
reportDropResult(IWindow window, boolean consumed)290     public void reportDropResult(IWindow window, boolean consumed) {
291         final long ident = Binder.clearCallingIdentity();
292         try {
293             mDragDropController.reportDropResult(window, consumed);
294         } finally {
295             Binder.restoreCallingIdentity(ident);
296         }
297     }
298 
299     @Override
cancelDragAndDrop(IBinder dragToken, boolean skipAnimation)300     public void cancelDragAndDrop(IBinder dragToken, boolean skipAnimation) {
301         final long ident = Binder.clearCallingIdentity();
302         try {
303             mDragDropController.cancelDragAndDrop(dragToken, skipAnimation);
304         } finally {
305             Binder.restoreCallingIdentity(ident);
306         }
307     }
308 
309     @Override
dragRecipientEntered(IWindow window)310     public void dragRecipientEntered(IWindow window) {
311         mDragDropController.dragRecipientEntered(window);
312     }
313 
314     @Override
dragRecipientExited(IWindow window)315     public void dragRecipientExited(IWindow window) {
316         mDragDropController.dragRecipientExited(window);
317     }
318 
319     @Override
startMovingTask(IWindow window, float startX, float startY)320     public boolean startMovingTask(IWindow window, float startX, float startY) {
321         if (DEBUG_TASK_POSITIONING) Slog.d(
322                 TAG_WM, "startMovingTask: {" + startX + "," + startY + "}");
323 
324         long ident = Binder.clearCallingIdentity();
325         try {
326             return mService.mTaskPositioningController.startMovingTask(window, startX, startY);
327         } finally {
328             Binder.restoreCallingIdentity(ident);
329         }
330     }
331 
332     @Override
finishMovingTask(IWindow window)333     public void finishMovingTask(IWindow window) {
334         if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "finishMovingTask");
335 
336         long ident = Binder.clearCallingIdentity();
337         try {
338             mService.mTaskPositioningController.finishTaskPositioning(window);
339         } finally {
340             Binder.restoreCallingIdentity(ident);
341         }
342     }
343 
344     @Override
reportSystemGestureExclusionChanged(IWindow window, List<Rect> exclusionRects)345     public void reportSystemGestureExclusionChanged(IWindow window, List<Rect> exclusionRects) {
346         long ident = Binder.clearCallingIdentity();
347         try {
348             mService.reportSystemGestureExclusionChanged(this, window, exclusionRects);
349         } finally {
350             Binder.restoreCallingIdentity(ident);
351         }
352     }
353 
actionOnWallpaper(IBinder window, BiConsumer<WallpaperController, WindowState> action)354     private void actionOnWallpaper(IBinder window,
355             BiConsumer<WallpaperController, WindowState> action) {
356         final WindowState windowState = mService.windowForClientLocked(this, window, true);
357         action.accept(windowState.getDisplayContent().mWallpaperController, windowState);
358     }
359 
360     @Override
setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep)361     public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
362         synchronized (mService.mGlobalLock) {
363             long ident = Binder.clearCallingIdentity();
364             try {
365                 actionOnWallpaper(window, (wpController, windowState) ->
366                         wpController.setWindowWallpaperPosition(windowState, x, y, xStep, yStep));
367             } finally {
368                 Binder.restoreCallingIdentity(ident);
369             }
370         }
371     }
372 
373     @Override
setWallpaperZoomOut(IBinder window, float zoom)374     public void setWallpaperZoomOut(IBinder window, float zoom) {
375         if (Float.compare(0f, zoom) > 0 || Float.compare(1f, zoom) < 0 || Float.isNaN(zoom)) {
376             throw new IllegalArgumentException("Zoom must be a valid float between 0 and 1: "
377                     + zoom);
378         }
379         synchronized (mService.mGlobalLock) {
380             long ident = Binder.clearCallingIdentity();
381             try {
382                 actionOnWallpaper(window, (wpController, windowState) ->
383                         wpController.setWallpaperZoomOut(windowState, zoom));
384             } finally {
385                 Binder.restoreCallingIdentity(ident);
386             }
387         }
388     }
389 
390     @Override
setShouldZoomOutWallpaper(IBinder window, boolean shouldZoom)391     public void setShouldZoomOutWallpaper(IBinder window, boolean shouldZoom) {
392         synchronized (mService.mGlobalLock) {
393             actionOnWallpaper(window, (wpController, windowState) ->
394                     wpController.setShouldZoomOutWallpaper(windowState, shouldZoom));
395         }
396     }
397 
398     @Override
wallpaperOffsetsComplete(IBinder window)399     public void wallpaperOffsetsComplete(IBinder window) {
400         synchronized (mService.mGlobalLock) {
401             actionOnWallpaper(window, (wpController, windowState) ->
402                     wpController.wallpaperOffsetsComplete(window));
403         }
404     }
405 
406     @Override
setWallpaperDisplayOffset(IBinder window, int x, int y)407     public void setWallpaperDisplayOffset(IBinder window, int x, int y) {
408         synchronized (mService.mGlobalLock) {
409             long ident = Binder.clearCallingIdentity();
410             try {
411                 actionOnWallpaper(window, (wpController, windowState) ->
412                         wpController.setWindowWallpaperDisplayOffset(windowState, x, y));
413             } finally {
414                 Binder.restoreCallingIdentity(ident);
415             }
416         }
417     }
418 
419     @Override
sendWallpaperCommand(IBinder window, String action, int x, int y, int z, Bundle extras, boolean sync)420     public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
421             int z, Bundle extras, boolean sync) {
422         synchronized (mService.mGlobalLock) {
423             long ident = Binder.clearCallingIdentity();
424             try {
425                 final WindowState windowState = mService.windowForClientLocked(this, window, true);
426                 return windowState.getDisplayContent().mWallpaperController
427                         .sendWindowWallpaperCommand(windowState, action, x, y, z, extras, sync);
428             } finally {
429                 Binder.restoreCallingIdentity(ident);
430             }
431         }
432     }
433 
434     @Override
wallpaperCommandComplete(IBinder window, Bundle result)435     public void wallpaperCommandComplete(IBinder window, Bundle result) {
436         synchronized (mService.mGlobalLock) {
437             actionOnWallpaper(window, (wpController, windowState) ->
438                     wpController.wallpaperCommandComplete(window));
439         }
440     }
441 
442     @Override
onRectangleOnScreenRequested(IBinder token, Rect rectangle)443     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
444         synchronized (mService.mGlobalLock) {
445             final long identity = Binder.clearCallingIdentity();
446             try {
447                 mService.onRectangleOnScreenRequested(token, rectangle);
448             } finally {
449                 Binder.restoreCallingIdentity(identity);
450             }
451         }
452     }
453 
454     @Override
getWindowId(IBinder window)455     public IWindowId getWindowId(IBinder window) {
456         return mService.getWindowId(window);
457     }
458 
459     @Override
pokeDrawLock(IBinder window)460     public void pokeDrawLock(IBinder window) {
461         final long identity = Binder.clearCallingIdentity();
462         try {
463             mService.pokeDrawLock(this, window);
464         } finally {
465             Binder.restoreCallingIdentity(identity);
466         }
467     }
468 
469     @Override
updatePointerIcon(IWindow window)470     public void updatePointerIcon(IWindow window) {
471         final long identity = Binder.clearCallingIdentity();
472         try {
473             mService.updatePointerIcon(window);
474         } finally {
475             Binder.restoreCallingIdentity(identity);
476         }
477     }
478 
479     @Override
reparentDisplayContent(IWindow window, SurfaceControl sc, int displayId)480     public void reparentDisplayContent(IWindow window, SurfaceControl sc, int displayId) {
481         mService.reparentDisplayContent(window, sc, displayId);
482     }
483 
484     @Override
updateDisplayContentLocation(IWindow window, int x, int y, int displayId)485     public void updateDisplayContentLocation(IWindow window, int x, int y, int displayId) {
486         mService.updateDisplayContentLocation(window, x, y, displayId);
487     }
488 
489     @Override
updateTapExcludeRegion(IWindow window, Region region)490     public void updateTapExcludeRegion(IWindow window, Region region) {
491         final long identity = Binder.clearCallingIdentity();
492         try {
493             mService.updateTapExcludeRegion(window, region);
494         } finally {
495             Binder.restoreCallingIdentity(identity);
496         }
497     }
498 
499     @Override
insetsModified(IWindow window, InsetsState state)500     public void insetsModified(IWindow window, InsetsState state) {
501         synchronized (mService.mGlobalLock) {
502             final WindowState windowState = mService.windowForClientLocked(this, window,
503                     false /* throwOnError */);
504             if (windowState != null) {
505                 windowState.updateRequestedInsetsState(state);
506                 windowState.getDisplayContent().getInsetsPolicy().onInsetsModified(
507                         windowState, state);
508             }
509         }
510     }
511 
windowAddedLocked(String packageName)512     void windowAddedLocked(String packageName) {
513         mPackageName = packageName;
514         mRelayoutTag = "relayoutWindow: " + mPackageName;
515         if (mSurfaceSession == null) {
516             if (DEBUG) {
517                 Slog.v(TAG_WM, "First window added to " + this + ", creating SurfaceSession");
518             }
519             mSurfaceSession = new SurfaceSession();
520             ProtoLog.i(WM_SHOW_TRANSACTIONS, "  NEW SURFACE SESSION %s", mSurfaceSession);
521             mService.mSessions.add(this);
522             if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
523                 mService.dispatchNewAnimatorScaleLocked(this);
524             }
525         }
526         mNumWindow++;
527     }
528 
windowRemovedLocked()529     void windowRemovedLocked() {
530         mNumWindow--;
531         killSessionLocked();
532     }
533 
534 
onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController, boolean visible, int type)535     void onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController,
536             boolean visible, int type) {
537 
538         if (!isSystemAlertWindowType(type)) {
539             return;
540         }
541 
542         boolean changed;
543 
544         if (!mCanAddInternalSystemWindow) {
545             // We want to track non-system signature apps adding alert windows so we can post an
546             // on-going notification for the user to control their visibility.
547             if (visible) {
548                 changed = mAlertWindowSurfaces.add(surfaceController);
549                 MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type, true);
550             } else {
551                 changed = mAlertWindowSurfaces.remove(surfaceController);
552                 MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type, true);
553             }
554 
555             if (changed) {
556                 if (mAlertWindowSurfaces.isEmpty()) {
557                     cancelAlertWindowNotification();
558                 } else if (mAlertWindowNotification == null){
559                     mAlertWindowNotification = new AlertWindowNotification(mService, mPackageName);
560                     if (mShowingAlertWindowNotificationAllowed) {
561                         mAlertWindowNotification.post();
562                     }
563                 }
564             }
565         }
566 
567         if (type != TYPE_APPLICATION_OVERLAY) {
568             return;
569         }
570 
571         if (visible) {
572             changed = mAppOverlaySurfaces.add(surfaceController);
573             MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type, false);
574         } else {
575             changed = mAppOverlaySurfaces.remove(surfaceController);
576             MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type, false);
577         }
578 
579         if (changed) {
580             // Notify activity manager of changes to app overlay windows so it can adjust the
581             // importance score for the process.
582             setHasOverlayUi(!mAppOverlaySurfaces.isEmpty());
583         }
584     }
585 
setShowingAlertWindowNotificationAllowed(boolean allowed)586     void setShowingAlertWindowNotificationAllowed(boolean allowed) {
587         mShowingAlertWindowNotificationAllowed = allowed;
588         if (mAlertWindowNotification != null) {
589             if (allowed) {
590                 mAlertWindowNotification.post();
591             } else {
592                 mAlertWindowNotification.cancel(false /* deleteChannel */);
593             }
594         }
595     }
596 
killSessionLocked()597     private void killSessionLocked() {
598         if (mNumWindow > 0 || !mClientDead) {
599             return;
600         }
601 
602         mService.mSessions.remove(this);
603         if (mSurfaceSession == null) {
604             return;
605         }
606 
607         if (DEBUG) {
608             Slog.v(TAG_WM, "Last window removed from " + this
609                     + ", destroying " + mSurfaceSession);
610         }
611         ProtoLog.i(WM_SHOW_TRANSACTIONS, "  KILL SURFACE SESSION %s", mSurfaceSession);
612         try {
613             mSurfaceSession.kill();
614         } catch (Exception e) {
615             Slog.w(TAG_WM, "Exception thrown when killing surface session " + mSurfaceSession
616                     + " in session " + this + ": " + e.toString());
617         }
618         mSurfaceSession = null;
619         mAlertWindowSurfaces.clear();
620         mAppOverlaySurfaces.clear();
621         setHasOverlayUi(false);
622         cancelAlertWindowNotification();
623     }
624 
setHasOverlayUi(boolean hasOverlayUi)625     private void setHasOverlayUi(boolean hasOverlayUi) {
626         mService.mH.obtainMessage(H.SET_HAS_OVERLAY_UI, mPid, hasOverlayUi ? 1 : 0).sendToTarget();
627     }
628 
cancelAlertWindowNotification()629     private void cancelAlertWindowNotification() {
630         if (mAlertWindowNotification == null) {
631             return;
632         }
633         mAlertWindowNotification.cancel(true /* deleteChannel */);
634         mAlertWindowNotification = null;
635     }
636 
dump(PrintWriter pw, String prefix)637     void dump(PrintWriter pw, String prefix) {
638         pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
639                 pw.print(" mCanAddInternalSystemWindow="); pw.print(mCanAddInternalSystemWindow);
640                 pw.print(" mAppOverlaySurfaces="); pw.print(mAppOverlaySurfaces);
641                 pw.print(" mAlertWindowSurfaces="); pw.print(mAlertWindowSurfaces);
642                 pw.print(" mClientDead="); pw.print(mClientDead);
643                 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
644         pw.print(prefix); pw.print("mPackageName="); pw.println(mPackageName);
645     }
646 
647     @Override
toString()648     public String toString() {
649         return mStringName;
650     }
651 
652     /** @return {@code true} if there is an alert window surface on the given display. */
hasAlertWindowSurfaces(DisplayContent displayContent)653     boolean hasAlertWindowSurfaces(DisplayContent displayContent) {
654         for (int i = mAlertWindowSurfaces.size() - 1; i >= 0; i--) {
655             final WindowSurfaceController surfaceController = mAlertWindowSurfaces.valueAt(i);
656             if (surfaceController.mAnimator.mWin.getDisplayContent() == displayContent) {
657                 return true;
658             }
659         }
660         return false;
661     }
662 
663     @Override
grantInputChannel(int displayId, SurfaceControl surface, IWindow window, IBinder hostInputToken, int flags, int type, InputChannel outInputChannel)664     public void grantInputChannel(int displayId, SurfaceControl surface,
665             IWindow window, IBinder hostInputToken, int flags, int type,
666             InputChannel outInputChannel) {
667         if (hostInputToken == null && !mCanAddInternalSystemWindow) {
668             // Callers without INTERNAL_SYSTEM_WINDOW permission cannot grant input channel to
669             // embedded windows without providing a host window input token
670             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
671         }
672 
673         if (!mCanAddInternalSystemWindow && type != 0) {
674             Slog.w(TAG_WM, "Requires INTERNAL_SYSTEM_WINDOW permission if assign type to"
675                     + " input");
676         }
677 
678         final long identity = Binder.clearCallingIdentity();
679         try {
680             mService.grantInputChannel(mUid, mPid, displayId, surface, window, hostInputToken,
681                     flags, mCanAddInternalSystemWindow ? type : 0, outInputChannel);
682         } finally {
683             Binder.restoreCallingIdentity(identity);
684         }
685     }
686 
687     @Override
updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface, int flags, Region region)688     public void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
689             int flags, Region region) {
690         final long identity = Binder.clearCallingIdentity();
691         try {
692             mService.updateInputChannel(channelToken, displayId, surface, flags, region);
693         } finally {
694             Binder.restoreCallingIdentity(identity);
695         }
696     }
697 }
698