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