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.os.Trace.TRACE_TAG_WINDOW_MANAGER;
22import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
23import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
24import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
25import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
26import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
27import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
28import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
29
30import android.content.ClipData;
31import android.content.Context;
32import android.graphics.Rect;
33import android.graphics.Region;
34import android.os.Binder;
35import android.os.Bundle;
36import android.os.IBinder;
37import android.os.Parcel;
38import android.os.Process;
39import android.os.RemoteException;
40import android.os.ServiceManager;
41import android.os.Trace;
42import android.os.UserHandle;
43import android.util.MergedConfiguration;
44import android.util.Slog;
45import android.view.Display;
46import android.view.IWindow;
47import android.view.IWindowId;
48import android.view.IWindowSession;
49import android.view.IWindowSessionCallback;
50import android.view.InputChannel;
51import android.view.Surface;
52import android.view.SurfaceControl;
53import android.view.SurfaceSession;
54import android.view.WindowManager;
55
56import com.android.internal.view.IInputContext;
57import com.android.internal.view.IInputMethodClient;
58import com.android.internal.view.IInputMethodManager;
59import com.android.server.wm.WindowManagerService.H;
60
61import java.io.PrintWriter;
62import java.util.HashSet;
63import 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 :(
70public 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
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
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
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
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
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
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
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
211    public void remove(IWindow window) {
212        mService.removeWindow(this, window);
213    }
214
215    @Override
216    public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) {
217        mService.setWillReplaceWindows(appToken, childrenOnly);
218    }
219
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
238    public boolean outOfMemory(IWindow window) {
239        return mService.outOfMemoryWindow(this, window);
240    }
241
242    public void setTransparentRegion(IWindow window, Region region) {
243        mService.setTransparentRegionWindow(this, window, region);
244    }
245
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
252    public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
253        mService.getWindowDisplayFrame(this, window, outDisplayFrame);
254    }
255
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
262    public void setInTouchMode(boolean mode) {
263        synchronized(mService.mWindowMap) {
264            mService.mInTouchMode = mode;
265        }
266    }
267
268    public boolean getInTouchMode() {
269        synchronized(mService.mWindowMap) {
270            return mService.mInTouchMode;
271        }
272    }
273
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 */
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
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
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
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
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
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
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
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
483    public void wallpaperOffsetsComplete(IBinder window) {
484        synchronized (mService.mWindowMap) {
485            mService.mRoot.mWallpaperController.wallpaperOffsetsComplete(window);
486        }
487    }
488
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
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
515    public void wallpaperCommandComplete(IBinder window, Bundle result) {
516        synchronized (mService.mWindowMap) {
517            mService.mRoot.mWallpaperController.wallpaperCommandComplete(window);
518        }
519    }
520
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
532    public IWindowId getWindowId(IBinder window) {
533        return mService.getWindowId(window);
534    }
535
536    @Override
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
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
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
573    void windowRemovedLocked() {
574        mNumWindow--;
575        killSessionLocked();
576    }
577
578
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
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
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
663    private void setHasOverlayUi(boolean hasOverlayUi) {
664        mService.mH.obtainMessage(H.SET_HAS_OVERLAY_UI, mPid, hasOverlayUi ? 1 : 0).sendToTarget();
665    }
666
667    private void cancelAlertWindowNotification() {
668        if (mAlertWindowNotification == null) {
669            return;
670        }
671        mAlertWindowNotification.cancel();
672        mAlertWindowNotification = null;
673    }
674
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
686    public String toString() {
687        return mStringName;
688    }
689}
690