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