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.INTERNAL_SYSTEM_WINDOW;
20 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
21 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
22 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
23 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
24 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
25 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
26 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
27 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
28 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
29 
30 import android.content.ClipData;
31 import android.content.Context;
32 import android.graphics.Rect;
33 import android.graphics.Region;
34 import android.os.Binder;
35 import android.os.Bundle;
36 import android.os.IBinder;
37 import android.os.Parcel;
38 import android.os.Process;
39 import android.os.RemoteException;
40 import android.os.ServiceManager;
41 import android.os.Trace;
42 import android.os.UserHandle;
43 import android.util.MergedConfiguration;
44 import android.util.Slog;
45 import android.view.Display;
46 import android.view.IWindow;
47 import android.view.IWindowId;
48 import android.view.IWindowSession;
49 import android.view.IWindowSessionCallback;
50 import android.view.InputChannel;
51 import android.view.Surface;
52 import android.view.SurfaceControl;
53 import android.view.SurfaceSession;
54 import android.view.WindowManager;
55 
56 import com.android.internal.view.IInputContext;
57 import com.android.internal.view.IInputMethodClient;
58 import com.android.internal.view.IInputMethodManager;
59 import com.android.server.wm.WindowManagerService.H;
60 
61 import java.io.PrintWriter;
62 import java.util.HashSet;
63 import java.util.Set;
64 
65 /**
66  * This class represents an active client session.  There is generally one
67  * Session object per process that is interacting with the window manager.
68  */
69 // Needs to be public and not final so we can mock during tests...sucks I know :(
70 public class Session extends IWindowSession.Stub
71         implements IBinder.DeathRecipient {
72     final WindowManagerService mService;
73     final IWindowSessionCallback mCallback;
74     final IInputMethodClient mClient;
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 Set<WindowSurfaceController> mAppOverlaySurfaces = new HashSet<>();
82     // Set of visible alert window surfaces connected to this session.
83     private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>();
84     final boolean mCanAddInternalSystemWindow;
85     private AlertWindowNotification mAlertWindowNotification;
86     private boolean mShowingAlertWindowNotificationAllowed;
87     private boolean mClientDead = false;
88     private float mLastReportedAnimatorScale;
89     private String mPackageName;
90     private String mRelayoutTag;
91 
Session(WindowManagerService service, IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext)92     public Session(WindowManagerService service, IWindowSessionCallback callback,
93             IInputMethodClient client, IInputContext inputContext) {
94         mService = service;
95         mCallback = callback;
96         mClient = client;
97         mUid = Binder.getCallingUid();
98         mPid = Binder.getCallingPid();
99         mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
100         mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission(
101                 INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
102         mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
103         StringBuilder sb = new StringBuilder();
104         sb.append("Session{");
105         sb.append(Integer.toHexString(System.identityHashCode(this)));
106         sb.append(" ");
107         sb.append(mPid);
108         if (mUid < Process.FIRST_APPLICATION_UID) {
109             sb.append(":");
110             sb.append(mUid);
111         } else {
112             sb.append(":u");
113             sb.append(UserHandle.getUserId(mUid));
114             sb.append('a');
115             sb.append(UserHandle.getAppId(mUid));
116         }
117         sb.append("}");
118         mStringName = sb.toString();
119 
120         synchronized (mService.mWindowMap) {
121             if (mService.mInputMethodManager == null && mService.mHaveInputMethods) {
122                 IBinder b = ServiceManager.getService(
123                         Context.INPUT_METHOD_SERVICE);
124                 mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
125             }
126         }
127         long ident = Binder.clearCallingIdentity();
128         try {
129             // Note: it is safe to call in to the input method manager
130             // here because we are not holding our lock.
131             if (mService.mInputMethodManager != null) {
132                 mService.mInputMethodManager.addClient(client, inputContext,
133                         mUid, mPid);
134             } else {
135                 client.setUsingInputMethod(false);
136             }
137             client.asBinder().linkToDeath(this, 0);
138         } catch (RemoteException e) {
139             // The caller has died, so we can just forget about this.
140             try {
141                 if (mService.mInputMethodManager != null) {
142                     mService.mInputMethodManager.removeClient(client);
143                 }
144             } catch (RemoteException ee) {
145             }
146         } finally {
147             Binder.restoreCallingIdentity(ident);
148         }
149     }
150 
151     @Override
onTransact(int code, Parcel data, Parcel reply, int flags)152     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
153             throws RemoteException {
154         try {
155             return super.onTransact(code, data, reply, flags);
156         } catch (RuntimeException e) {
157             // Log all 'real' exceptions thrown to the caller
158             if (!(e instanceof SecurityException)) {
159                 Slog.wtf(TAG_WM, "Window Session Crash", e);
160             }
161             throw e;
162         }
163     }
164 
binderDied()165     public void binderDied() {
166         // Note: it is safe to call in to the input method manager
167         // here because we are not holding our lock.
168         try {
169             if (mService.mInputMethodManager != null) {
170                 mService.mInputMethodManager.removeClient(mClient);
171             }
172         } catch (RemoteException e) {
173         }
174         synchronized(mService.mWindowMap) {
175             mClient.asBinder().unlinkToDeath(this, 0);
176             mClientDead = true;
177             killSessionLocked();
178         }
179     }
180 
181     @Override
add(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, Rect outContentInsets, Rect outStableInsets, InputChannel outInputChannel)182     public int add(IWindow window, int seq, WindowManager.LayoutParams attrs,
183             int viewVisibility, Rect outContentInsets, Rect outStableInsets,
184             InputChannel outInputChannel) {
185         return addToDisplay(window, seq, attrs, viewVisibility, Display.DEFAULT_DISPLAY,
186                 outContentInsets, outStableInsets, null /* outOutsets */, outInputChannel);
187     }
188 
189     @Override
addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel)190     public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
191             int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
192             Rect outOutsets, InputChannel outInputChannel) {
193         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
194                 outContentInsets, outStableInsets, outOutsets, outInputChannel);
195     }
196 
197     @Override
addWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, Rect outContentInsets, Rect outStableInsets)198     public int addWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
199             int viewVisibility, Rect outContentInsets, Rect outStableInsets) {
200         return addToDisplayWithoutInputChannel(window, seq, attrs, viewVisibility,
201                 Display.DEFAULT_DISPLAY, outContentInsets, outStableInsets);
202     }
203 
204     @Override
addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets)205     public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
206             int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets) {
207         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
208             outContentInsets, outStableInsets, null /* outOutsets */, null);
209     }
210 
remove(IWindow window)211     public void remove(IWindow window) {
212         mService.removeWindow(this, window);
213     }
214 
215     @Override
prepareToReplaceWindows(IBinder appToken, boolean childrenOnly)216     public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) {
217         mService.setWillReplaceWindows(appToken, childrenOnly);
218     }
219 
relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame, MergedConfiguration mergedConfiguration, Surface outSurface)220     public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
221             int requestedWidth, int requestedHeight, int viewFlags,
222             int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
223             Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
224             MergedConfiguration mergedConfiguration, Surface outSurface) {
225         if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
226                 + Binder.getCallingPid());
227         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
228         int res = mService.relayoutWindow(this, window, seq, attrs,
229                 requestedWidth, requestedHeight, viewFlags, flags,
230                 outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
231                 outStableInsets, outsets, outBackdropFrame, mergedConfiguration, outSurface);
232         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
233         if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
234                 + Binder.getCallingPid());
235         return res;
236     }
237 
outOfMemory(IWindow window)238     public boolean outOfMemory(IWindow window) {
239         return mService.outOfMemoryWindow(this, window);
240     }
241 
setTransparentRegion(IWindow window, Region region)242     public void setTransparentRegion(IWindow window, Region region) {
243         mService.setTransparentRegionWindow(this, window, region);
244     }
245 
setInsets(IWindow window, int touchableInsets, Rect contentInsets, Rect visibleInsets, Region touchableArea)246     public void setInsets(IWindow window, int touchableInsets,
247             Rect contentInsets, Rect visibleInsets, Region touchableArea) {
248         mService.setInsetsWindow(this, window, touchableInsets, contentInsets,
249                 visibleInsets, touchableArea);
250     }
251 
getDisplayFrame(IWindow window, Rect outDisplayFrame)252     public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
253         mService.getWindowDisplayFrame(this, window, outDisplayFrame);
254     }
255 
finishDrawing(IWindow window)256     public void finishDrawing(IWindow window) {
257         if (WindowManagerService.localLOGV) Slog.v(
258             TAG_WM, "IWindow finishDrawing called for " + window);
259         mService.finishDrawingWindow(this, window);
260     }
261 
setInTouchMode(boolean mode)262     public void setInTouchMode(boolean mode) {
263         synchronized(mService.mWindowMap) {
264             mService.mInTouchMode = mode;
265         }
266     }
267 
getInTouchMode()268     public boolean getInTouchMode() {
269         synchronized(mService.mWindowMap) {
270             return mService.mInTouchMode;
271         }
272     }
273 
performHapticFeedback(IWindow window, int effectId, boolean always)274     public boolean performHapticFeedback(IWindow window, int effectId,
275             boolean always) {
276         synchronized(mService.mWindowMap) {
277             long ident = Binder.clearCallingIdentity();
278             try {
279                 return mService.mPolicy.performHapticFeedbackLw(
280                         mService.windowForClientLocked(this, window, true),
281                         effectId, always);
282             } finally {
283                 Binder.restoreCallingIdentity(ident);
284             }
285         }
286     }
287 
288     /* Drag/drop */
prepareDrag(IWindow window, int flags, int width, int height, Surface outSurface)289     public IBinder prepareDrag(IWindow window, int flags,
290             int width, int height, Surface outSurface) {
291         return mService.prepareDragSurface(window, mSurfaceSession, flags,
292                 width, height, outSurface);
293     }
294 
performDrag(IWindow window, IBinder dragToken, int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data)295     public boolean performDrag(IWindow window, IBinder dragToken,
296             int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
297             ClipData data) {
298         if (DEBUG_DRAG) {
299             Slog.d(TAG_WM, "perform drag: win=" + window + " data=" + data);
300         }
301 
302         synchronized (mService.mWindowMap) {
303             if (mService.mDragState == null) {
304                 Slog.w(TAG_WM, "No drag prepared");
305                 throw new IllegalStateException("performDrag() without prepareDrag()");
306             }
307 
308             if (dragToken != mService.mDragState.mToken) {
309                 Slog.w(TAG_WM, "Performing mismatched drag");
310                 throw new IllegalStateException("performDrag() does not match prepareDrag()");
311             }
312 
313             WindowState callingWin = mService.windowForClientLocked(null, window, false);
314             if (callingWin == null) {
315                 Slog.w(TAG_WM, "Bad requesting window " + window);
316                 return false;  // !!! TODO: throw here?
317             }
318 
319             // !!! TODO: if input is not still focused on the initiating window, fail
320             // the drag initiation (e.g. an alarm window popped up just as the application
321             // called performDrag()
322 
323             mService.mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder());
324 
325             // !!! TODO: extract the current touch (x, y) in screen coordinates.  That
326             // will let us eliminate the (touchX,touchY) parameters from the API.
327 
328             // !!! FIXME: put all this heavy stuff onto the mH looper, as well as
329             // the actual drag event dispatch stuff in the dragstate
330 
331             final DisplayContent displayContent = callingWin.getDisplayContent();
332             if (displayContent == null) {
333                return false;
334             }
335             Display display = displayContent.getDisplay();
336             mService.mDragState.register(display);
337             if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
338                     mService.mDragState.getInputChannel())) {
339                 Slog.e(TAG_WM, "Unable to transfer touch focus");
340                 mService.mDragState.unregister();
341                 mService.mDragState.reset();
342                 mService.mDragState = null;
343                 return false;
344             }
345 
346             mService.mDragState.mDisplayContent = displayContent;
347             mService.mDragState.mData = data;
348             mService.mDragState.broadcastDragStartedLw(touchX, touchY);
349             mService.mDragState.overridePointerIconLw(touchSource);
350 
351             // remember the thumb offsets for later
352             mService.mDragState.mThumbOffsetX = thumbCenterX;
353             mService.mDragState.mThumbOffsetY = thumbCenterY;
354 
355             // Make the surface visible at the proper location
356             final SurfaceControl surfaceControl = mService.mDragState.mSurfaceControl;
357             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
358                     TAG_WM, ">>> OPEN TRANSACTION performDrag");
359             mService.openSurfaceTransaction();
360             try {
361                 surfaceControl.setPosition(touchX - thumbCenterX,
362                         touchY - thumbCenterY);
363                 surfaceControl.setLayer(mService.mDragState.getDragLayerLw());
364                 surfaceControl.setLayerStack(display.getLayerStack());
365                 surfaceControl.show();
366             } finally {
367                 mService.closeSurfaceTransaction();
368                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
369                         TAG_WM, "<<< CLOSE TRANSACTION performDrag");
370             }
371 
372             mService.mDragState.notifyLocationLw(touchX, touchY);
373         }
374 
375         return true;    // success!
376     }
377 
startMovingTask(IWindow window, float startX, float startY)378     public boolean startMovingTask(IWindow window, float startX, float startY) {
379         if (DEBUG_TASK_POSITIONING) Slog.d(
380                 TAG_WM, "startMovingTask: {" + startX + "," + startY + "}");
381 
382         long ident = Binder.clearCallingIdentity();
383         try {
384             return mService.startMovingTask(window, startX, startY);
385         } finally {
386             Binder.restoreCallingIdentity(ident);
387         }
388     }
389 
reportDropResult(IWindow window, boolean consumed)390     public void reportDropResult(IWindow window, boolean consumed) {
391         IBinder token = window.asBinder();
392         if (DEBUG_DRAG) {
393             Slog.d(TAG_WM, "Drop result=" + consumed + " reported by " + token);
394         }
395 
396         synchronized (mService.mWindowMap) {
397             long ident = Binder.clearCallingIdentity();
398             try {
399                 if (mService.mDragState == null) {
400                     // Most likely the drop recipient ANRed and we ended the drag
401                     // out from under it.  Log the issue and move on.
402                     Slog.w(TAG_WM, "Drop result given but no drag in progress");
403                     return;
404                 }
405 
406                 if (mService.mDragState.mToken != token) {
407                     // We're in a drag, but the wrong window has responded.
408                     Slog.w(TAG_WM, "Invalid drop-result claim by " + window);
409                     throw new IllegalStateException("reportDropResult() by non-recipient");
410                 }
411 
412                 // The right window has responded, even if it's no longer around,
413                 // so be sure to halt the timeout even if the later WindowState
414                 // lookup fails.
415                 mService.mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());
416                 WindowState callingWin = mService.windowForClientLocked(null, window, false);
417                 if (callingWin == null) {
418                     Slog.w(TAG_WM, "Bad result-reporting window " + window);
419                     return;  // !!! TODO: throw here?
420                 }
421 
422                 mService.mDragState.mDragResult = consumed;
423                 mService.mDragState.endDragLw();
424             } finally {
425                 Binder.restoreCallingIdentity(ident);
426             }
427         }
428     }
429 
cancelDragAndDrop(IBinder dragToken)430     public void cancelDragAndDrop(IBinder dragToken) {
431         if (DEBUG_DRAG) {
432             Slog.d(TAG_WM, "cancelDragAndDrop");
433         }
434 
435         synchronized (mService.mWindowMap) {
436             long ident = Binder.clearCallingIdentity();
437             try {
438                 if (mService.mDragState == null) {
439                     Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()");
440                     throw new IllegalStateException("cancelDragAndDrop() without prepareDrag()");
441                 }
442 
443                 if (mService.mDragState.mToken != dragToken) {
444                     Slog.w(TAG_WM,
445                             "cancelDragAndDrop() does not match prepareDrag()");
446                     throw new IllegalStateException(
447                             "cancelDragAndDrop() does not match prepareDrag()");
448                 }
449 
450                 mService.mDragState.mDragResult = false;
451                 mService.mDragState.cancelDragLw();
452             } finally {
453                 Binder.restoreCallingIdentity(ident);
454             }
455         }
456     }
457 
dragRecipientEntered(IWindow window)458     public void dragRecipientEntered(IWindow window) {
459         if (DEBUG_DRAG) {
460             Slog.d(TAG_WM, "Drag into new candidate view @ " + window.asBinder());
461         }
462     }
463 
dragRecipientExited(IWindow window)464     public void dragRecipientExited(IWindow window) {
465         if (DEBUG_DRAG) {
466             Slog.d(TAG_WM, "Drag from old candidate view @ " + window.asBinder());
467         }
468     }
469 
setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep)470     public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
471         synchronized(mService.mWindowMap) {
472             long ident = Binder.clearCallingIdentity();
473             try {
474                 mService.mRoot.mWallpaperController.setWindowWallpaperPosition(
475                         mService.windowForClientLocked(this, window, true),
476                         x, y, xStep, yStep);
477             } finally {
478                 Binder.restoreCallingIdentity(ident);
479             }
480         }
481     }
482 
wallpaperOffsetsComplete(IBinder window)483     public void wallpaperOffsetsComplete(IBinder window) {
484         synchronized (mService.mWindowMap) {
485             mService.mRoot.mWallpaperController.wallpaperOffsetsComplete(window);
486         }
487     }
488 
setWallpaperDisplayOffset(IBinder window, int x, int y)489     public void setWallpaperDisplayOffset(IBinder window, int x, int y) {
490         synchronized(mService.mWindowMap) {
491             long ident = Binder.clearCallingIdentity();
492             try {
493                 mService.mRoot.mWallpaperController.setWindowWallpaperDisplayOffset(
494                         mService.windowForClientLocked(this, window, true), x, y);
495             } finally {
496                 Binder.restoreCallingIdentity(ident);
497             }
498         }
499     }
500 
sendWallpaperCommand(IBinder window, String action, int x, int y, int z, Bundle extras, boolean sync)501     public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
502             int z, Bundle extras, boolean sync) {
503         synchronized(mService.mWindowMap) {
504             long ident = Binder.clearCallingIdentity();
505             try {
506                 return mService.mRoot.mWallpaperController.sendWindowWallpaperCommand(
507                         mService.windowForClientLocked(this, window, true),
508                         action, x, y, z, extras, sync);
509             } finally {
510                 Binder.restoreCallingIdentity(ident);
511             }
512         }
513     }
514 
wallpaperCommandComplete(IBinder window, Bundle result)515     public void wallpaperCommandComplete(IBinder window, Bundle result) {
516         synchronized (mService.mWindowMap) {
517             mService.mRoot.mWallpaperController.wallpaperCommandComplete(window);
518         }
519     }
520 
onRectangleOnScreenRequested(IBinder token, Rect rectangle)521     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
522         synchronized(mService.mWindowMap) {
523             final long identity = Binder.clearCallingIdentity();
524             try {
525                 mService.onRectangleOnScreenRequested(token, rectangle);
526             } finally {
527                 Binder.restoreCallingIdentity(identity);
528             }
529         }
530     }
531 
getWindowId(IBinder window)532     public IWindowId getWindowId(IBinder window) {
533         return mService.getWindowId(window);
534     }
535 
536     @Override
pokeDrawLock(IBinder window)537     public void pokeDrawLock(IBinder window) {
538         final long identity = Binder.clearCallingIdentity();
539         try {
540             mService.pokeDrawLock(this, window);
541         } finally {
542             Binder.restoreCallingIdentity(identity);
543         }
544     }
545 
546     @Override
updatePointerIcon(IWindow window)547     public void updatePointerIcon(IWindow window) {
548         final long identity = Binder.clearCallingIdentity();
549         try {
550             mService.updatePointerIcon(window);
551         } finally {
552             Binder.restoreCallingIdentity(identity);
553         }
554     }
555 
windowAddedLocked(String packageName)556     void windowAddedLocked(String packageName) {
557         mPackageName = packageName;
558         mRelayoutTag = "relayoutWindow: " + mPackageName;
559         if (mSurfaceSession == null) {
560             if (WindowManagerService.localLOGV) Slog.v(
561                 TAG_WM, "First window added to " + this + ", creating SurfaceSession");
562             mSurfaceSession = new SurfaceSession();
563             if (SHOW_TRANSACTIONS) Slog.i(
564                     TAG_WM, "  NEW SURFACE SESSION " + mSurfaceSession);
565             mService.mSessions.add(this);
566             if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
567                 mService.dispatchNewAnimatorScaleLocked(this);
568             }
569         }
570         mNumWindow++;
571     }
572 
windowRemovedLocked()573     void windowRemovedLocked() {
574         mNumWindow--;
575         killSessionLocked();
576     }
577 
578 
onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController, boolean visible, int type)579     void onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController,
580             boolean visible, int type) {
581 
582         if (!isSystemAlertWindowType(type)) {
583             return;
584         }
585 
586         boolean changed;
587 
588         if (!mCanAddInternalSystemWindow) {
589             // We want to track non-system signature apps adding alert windows so we can post an
590             // on-going notification for the user to control their visibility.
591             if (visible) {
592                 changed = mAlertWindowSurfaces.add(surfaceController);
593             } else {
594                 changed = mAlertWindowSurfaces.remove(surfaceController);
595             }
596 
597             if (changed) {
598                 if (mAlertWindowSurfaces.isEmpty()) {
599                     cancelAlertWindowNotification();
600                 } else if (mAlertWindowNotification == null){
601                     mAlertWindowNotification = new AlertWindowNotification(mService, mPackageName);
602                     if (mShowingAlertWindowNotificationAllowed) {
603                         mAlertWindowNotification.post();
604                     }
605                 }
606             }
607         }
608 
609         if (type != TYPE_APPLICATION_OVERLAY) {
610             return;
611         }
612 
613         if (visible) {
614             changed = mAppOverlaySurfaces.add(surfaceController);
615         } else {
616             changed = mAppOverlaySurfaces.remove(surfaceController);
617         }
618 
619         if (changed) {
620             // Notify activity manager of changes to app overlay windows so it can adjust the
621             // importance score for the process.
622             setHasOverlayUi(!mAppOverlaySurfaces.isEmpty());
623         }
624     }
625 
setShowingAlertWindowNotificationAllowed(boolean allowed)626     void setShowingAlertWindowNotificationAllowed(boolean allowed) {
627         mShowingAlertWindowNotificationAllowed = allowed;
628         if (mAlertWindowNotification != null) {
629             if (allowed) {
630                 mAlertWindowNotification.post();
631             } else {
632                 mAlertWindowNotification.cancel();
633             }
634         }
635     }
636 
killSessionLocked()637     private void killSessionLocked() {
638         if (mNumWindow > 0 || !mClientDead) {
639             return;
640         }
641 
642         mService.mSessions.remove(this);
643         if (mSurfaceSession == null) {
644             return;
645         }
646 
647         if (WindowManagerService.localLOGV) Slog.v(TAG_WM, "Last window removed from " + this
648                 + ", destroying " + mSurfaceSession);
649         if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  KILL SURFACE SESSION " + mSurfaceSession);
650         try {
651             mSurfaceSession.kill();
652         } catch (Exception e) {
653             Slog.w(TAG_WM, "Exception thrown when killing surface session " + mSurfaceSession
654                     + " in session " + this + ": " + e.toString());
655         }
656         mSurfaceSession = null;
657         mAlertWindowSurfaces.clear();
658         mAppOverlaySurfaces.clear();
659         setHasOverlayUi(false);
660         cancelAlertWindowNotification();
661     }
662 
setHasOverlayUi(boolean hasOverlayUi)663     private void setHasOverlayUi(boolean hasOverlayUi) {
664         mService.mH.obtainMessage(H.SET_HAS_OVERLAY_UI, mPid, hasOverlayUi ? 1 : 0).sendToTarget();
665     }
666 
cancelAlertWindowNotification()667     private void cancelAlertWindowNotification() {
668         if (mAlertWindowNotification == null) {
669             return;
670         }
671         mAlertWindowNotification.cancel();
672         mAlertWindowNotification = null;
673     }
674 
dump(PrintWriter pw, String prefix)675     void dump(PrintWriter pw, String prefix) {
676         pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
677                 pw.print(" mCanAddInternalSystemWindow="); pw.print(mCanAddInternalSystemWindow);
678                 pw.print(" mAppOverlaySurfaces="); pw.print(mAppOverlaySurfaces);
679                 pw.print(" mAlertWindowSurfaces="); pw.print(mAlertWindowSurfaces);
680                 pw.print(" mClientDead="); pw.print(mClientDead);
681                 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
682         pw.print(prefix); pw.print("mPackageName="); pw.println(mPackageName);
683     }
684 
685     @Override
toString()686     public String toString() {
687         return mStringName;
688     }
689 }
690