Home | History | Annotate | Download | only in wm
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.wm;
     18 
     19 import static android.Manifest.permission.DEVICE_POWER;
     20 import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
     21 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
     22 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
     23 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
     24 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
     25 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
     26 
     27 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
     28 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
     29 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
     30 
     31 import android.content.ClipData;
     32 import android.content.Context;
     33 import android.graphics.Rect;
     34 import android.graphics.Region;
     35 import android.os.Binder;
     36 import android.os.Bundle;
     37 import android.os.IBinder;
     38 import android.os.Parcel;
     39 import android.os.Process;
     40 import android.os.RemoteException;
     41 import android.os.ServiceManager;
     42 import android.os.Trace;
     43 import android.os.UserHandle;
     44 import android.util.MergedConfiguration;
     45 import android.util.Slog;
     46 import android.view.Display;
     47 import android.view.DisplayCutout;
     48 import android.view.IWindow;
     49 import android.view.IWindowId;
     50 import android.view.IWindowSession;
     51 import android.view.IWindowSessionCallback;
     52 import android.view.InputChannel;
     53 import android.view.Surface;
     54 import android.view.SurfaceControl;
     55 import android.view.SurfaceSession;
     56 import android.view.WindowManager;
     57 
     58 import com.android.internal.os.logging.MetricsLoggerWrapper;
     59 import com.android.internal.view.IInputContext;
     60 import com.android.internal.view.IInputMethodClient;
     61 import com.android.internal.view.IInputMethodManager;
     62 import com.android.server.wm.WindowManagerService.H;
     63 
     64 import java.io.PrintWriter;
     65 import java.util.HashSet;
     66 import java.util.Set;
     67 
     68 /**
     69  * This class represents an active client session.  There is generally one
     70  * Session object per process that is interacting with the window manager.
     71  */
     72 class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
     73     final WindowManagerService mService;
     74     final IWindowSessionCallback mCallback;
     75     final IInputMethodClient mClient;
     76     final int mUid;
     77     final int mPid;
     78     private final String mStringName;
     79     SurfaceSession mSurfaceSession;
     80     private int mNumWindow = 0;
     81     // Set of visible application overlay window surfaces connected to this session.
     82     private final Set<WindowSurfaceController> mAppOverlaySurfaces = new HashSet<>();
     83     // Set of visible alert window surfaces connected to this session.
     84     private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>();
     85     private final DragDropController mDragDropController;
     86     final boolean mCanAddInternalSystemWindow;
     87     final boolean mCanHideNonSystemOverlayWindows;
     88     final boolean mCanAcquireSleepToken;
     89     private AlertWindowNotification mAlertWindowNotification;
     90     private boolean mShowingAlertWindowNotificationAllowed;
     91     private boolean mClientDead = false;
     92     private float mLastReportedAnimatorScale;
     93     private String mPackageName;
     94     private String mRelayoutTag;
     95 
     96     public Session(WindowManagerService service, IWindowSessionCallback callback,
     97             IInputMethodClient client, IInputContext inputContext) {
     98         mService = service;
     99         mCallback = callback;
    100         mClient = client;
    101         mUid = Binder.getCallingUid();
    102         mPid = Binder.getCallingPid();
    103         mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
    104         mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission(
    105                 INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
    106         mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission(
    107                 HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED;
    108         mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER)
    109                 == PERMISSION_GRANTED;
    110         mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
    111         mDragDropController = mService.mDragDropController;
    112         StringBuilder sb = new StringBuilder();
    113         sb.append("Session{");
    114         sb.append(Integer.toHexString(System.identityHashCode(this)));
    115         sb.append(" ");
    116         sb.append(mPid);
    117         if (mUid < Process.FIRST_APPLICATION_UID) {
    118             sb.append(":");
    119             sb.append(mUid);
    120         } else {
    121             sb.append(":u");
    122             sb.append(UserHandle.getUserId(mUid));
    123             sb.append('a');
    124             sb.append(UserHandle.getAppId(mUid));
    125         }
    126         sb.append("}");
    127         mStringName = sb.toString();
    128 
    129         synchronized (mService.mWindowMap) {
    130             if (mService.mInputMethodManager == null && mService.mHaveInputMethods) {
    131                 IBinder b = ServiceManager.getService(
    132                         Context.INPUT_METHOD_SERVICE);
    133                 mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
    134             }
    135         }
    136         long ident = Binder.clearCallingIdentity();
    137         try {
    138             // Note: it is safe to call in to the input method manager
    139             // here because we are not holding our lock.
    140             if (mService.mInputMethodManager != null) {
    141                 mService.mInputMethodManager.addClient(client, inputContext,
    142                         mUid, mPid);
    143             } else {
    144                 client.setUsingInputMethod(false);
    145             }
    146             client.asBinder().linkToDeath(this, 0);
    147         } catch (RemoteException e) {
    148             // The caller has died, so we can just forget about this.
    149             try {
    150                 if (mService.mInputMethodManager != null) {
    151                     mService.mInputMethodManager.removeClient(client);
    152                 }
    153             } catch (RemoteException ee) {
    154             }
    155         } finally {
    156             Binder.restoreCallingIdentity(ident);
    157         }
    158     }
    159 
    160     @Override
    161     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
    162             throws RemoteException {
    163         try {
    164             return super.onTransact(code, data, reply, flags);
    165         } catch (RuntimeException e) {
    166             // Log all 'real' exceptions thrown to the caller
    167             if (!(e instanceof SecurityException)) {
    168                 Slog.wtf(TAG_WM, "Window Session Crash", e);
    169             }
    170             throw e;
    171         }
    172     }
    173 
    174     @Override
    175     public void binderDied() {
    176         // Note: it is safe to call in to the input method manager
    177         // here because we are not holding our lock.
    178         try {
    179             if (mService.mInputMethodManager != null) {
    180                 mService.mInputMethodManager.removeClient(mClient);
    181             }
    182         } catch (RemoteException e) {
    183         }
    184         synchronized(mService.mWindowMap) {
    185             mClient.asBinder().unlinkToDeath(this, 0);
    186             mClientDead = true;
    187             killSessionLocked();
    188         }
    189     }
    190 
    191     @Override
    192     public int add(IWindow window, int seq, WindowManager.LayoutParams attrs,
    193             int viewVisibility, Rect outContentInsets, Rect outStableInsets,
    194             InputChannel outInputChannel) {
    195         return addToDisplay(window, seq, attrs, viewVisibility, Display.DEFAULT_DISPLAY,
    196                 new Rect() /* outFrame */, outContentInsets, outStableInsets, null /* outOutsets */,
    197                 new DisplayCutout.ParcelableWrapper()  /* cutout */, outInputChannel);
    198     }
    199 
    200     @Override
    201     public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
    202             int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
    203             Rect outStableInsets, Rect outOutsets,
    204             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
    205         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
    206                 outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
    207     }
    208 
    209     @Override
    210     public int addWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
    211             int viewVisibility, Rect outContentInsets, Rect outStableInsets) {
    212         return addToDisplayWithoutInputChannel(window, seq, attrs, viewVisibility,
    213                 Display.DEFAULT_DISPLAY, outContentInsets, outStableInsets);
    214     }
    215 
    216     @Override
    217     public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
    218             int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets) {
    219         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
    220                 new Rect() /* outFrame */, outContentInsets, outStableInsets, null /* outOutsets */,
    221                 new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */);
    222     }
    223 
    224     @Override
    225     public void remove(IWindow window) {
    226         mService.removeWindow(this, window);
    227     }
    228 
    229     @Override
    230     public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) {
    231         mService.setWillReplaceWindows(appToken, childrenOnly);
    232     }
    233 
    234     @Override
    235     public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
    236             int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
    237             Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
    238             Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
    239             DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
    240             Surface outSurface) {
    241         if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
    242                 + Binder.getCallingPid());
    243         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
    244         int res = mService.relayoutWindow(this, window, seq, attrs,
    245                 requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
    246                 outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
    247                 outStableInsets, outsets, outBackdropFrame, cutout,
    248                 mergedConfiguration, outSurface);
    249         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    250         if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
    251                 + Binder.getCallingPid());
    252         return res;
    253     }
    254 
    255     @Override
    256     public boolean outOfMemory(IWindow window) {
    257         return mService.outOfMemoryWindow(this, window);
    258     }
    259 
    260     @Override
    261     public void setTransparentRegion(IWindow window, Region region) {
    262         mService.setTransparentRegionWindow(this, window, region);
    263     }
    264 
    265     @Override
    266     public void setInsets(IWindow window, int touchableInsets,
    267             Rect contentInsets, Rect visibleInsets, Region touchableArea) {
    268         mService.setInsetsWindow(this, window, touchableInsets, contentInsets,
    269                 visibleInsets, touchableArea);
    270     }
    271 
    272     @Override
    273     public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
    274         mService.getWindowDisplayFrame(this, window, outDisplayFrame);
    275     }
    276 
    277     @Override
    278     public void finishDrawing(IWindow window) {
    279         if (WindowManagerService.localLOGV) Slog.v(
    280             TAG_WM, "IWindow finishDrawing called for " + window);
    281         mService.finishDrawingWindow(this, window);
    282     }
    283 
    284     @Override
    285     public void setInTouchMode(boolean mode) {
    286         synchronized(mService.mWindowMap) {
    287             mService.mInTouchMode = mode;
    288         }
    289     }
    290 
    291     @Override
    292     public boolean getInTouchMode() {
    293         synchronized(mService.mWindowMap) {
    294             return mService.mInTouchMode;
    295         }
    296     }
    297 
    298     @Override
    299     public boolean performHapticFeedback(IWindow window, int effectId,
    300             boolean always) {
    301         synchronized(mService.mWindowMap) {
    302             long ident = Binder.clearCallingIdentity();
    303             try {
    304                 return mService.mPolicy.performHapticFeedbackLw(
    305                         mService.windowForClientLocked(this, window, true),
    306                         effectId, always);
    307             } finally {
    308                 Binder.restoreCallingIdentity(ident);
    309             }
    310         }
    311     }
    312 
    313     /* Drag/drop */
    314 
    315     @Override
    316     public IBinder performDrag(IWindow window, int flags, SurfaceControl surface, int touchSource,
    317             float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data) {
    318         final int callerPid = Binder.getCallingPid();
    319         final int callerUid = Binder.getCallingUid();
    320         final long ident = Binder.clearCallingIdentity();
    321         try {
    322             return mDragDropController.performDrag(mSurfaceSession, callerPid, callerUid, window,
    323                     flags, surface, touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data);
    324         } finally {
    325             Binder.restoreCallingIdentity(ident);
    326         }
    327     }
    328 
    329     @Override
    330     public void reportDropResult(IWindow window, boolean consumed) {
    331         final long ident = Binder.clearCallingIdentity();
    332         try {
    333             mDragDropController.reportDropResult(window, consumed);
    334         } finally {
    335             Binder.restoreCallingIdentity(ident);
    336         }
    337     }
    338 
    339     @Override
    340     public void cancelDragAndDrop(IBinder dragToken) {
    341         final long ident = Binder.clearCallingIdentity();
    342         try {
    343             mDragDropController.cancelDragAndDrop(dragToken);
    344         } finally {
    345             Binder.restoreCallingIdentity(ident);
    346         }
    347     }
    348 
    349     @Override
    350     public void dragRecipientEntered(IWindow window) {
    351         mDragDropController.dragRecipientEntered(window);
    352     }
    353 
    354     @Override
    355     public void dragRecipientExited(IWindow window) {
    356         mDragDropController.dragRecipientExited(window);
    357     }
    358 
    359     @Override
    360     public boolean startMovingTask(IWindow window, float startX, float startY) {
    361         if (DEBUG_TASK_POSITIONING) Slog.d(
    362                 TAG_WM, "startMovingTask: {" + startX + "," + startY + "}");
    363 
    364         long ident = Binder.clearCallingIdentity();
    365         try {
    366             return mService.mTaskPositioningController.startMovingTask(window, startX, startY);
    367         } finally {
    368             Binder.restoreCallingIdentity(ident);
    369         }
    370     }
    371 
    372     @Override
    373     public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
    374         synchronized(mService.mWindowMap) {
    375             long ident = Binder.clearCallingIdentity();
    376             try {
    377                 mService.mRoot.mWallpaperController.setWindowWallpaperPosition(
    378                         mService.windowForClientLocked(this, window, true),
    379                         x, y, xStep, yStep);
    380             } finally {
    381                 Binder.restoreCallingIdentity(ident);
    382             }
    383         }
    384     }
    385 
    386     @Override
    387     public void wallpaperOffsetsComplete(IBinder window) {
    388         synchronized (mService.mWindowMap) {
    389             mService.mRoot.mWallpaperController.wallpaperOffsetsComplete(window);
    390         }
    391     }
    392 
    393     @Override
    394     public void setWallpaperDisplayOffset(IBinder window, int x, int y) {
    395         synchronized(mService.mWindowMap) {
    396             long ident = Binder.clearCallingIdentity();
    397             try {
    398                 mService.mRoot.mWallpaperController.setWindowWallpaperDisplayOffset(
    399                         mService.windowForClientLocked(this, window, true), x, y);
    400             } finally {
    401                 Binder.restoreCallingIdentity(ident);
    402             }
    403         }
    404     }
    405 
    406     @Override
    407     public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
    408             int z, Bundle extras, boolean sync) {
    409         synchronized(mService.mWindowMap) {
    410             long ident = Binder.clearCallingIdentity();
    411             try {
    412                 return mService.mRoot.mWallpaperController.sendWindowWallpaperCommand(
    413                         mService.windowForClientLocked(this, window, true),
    414                         action, x, y, z, extras, sync);
    415             } finally {
    416                 Binder.restoreCallingIdentity(ident);
    417             }
    418         }
    419     }
    420 
    421     @Override
    422     public void wallpaperCommandComplete(IBinder window, Bundle result) {
    423         synchronized (mService.mWindowMap) {
    424             mService.mRoot.mWallpaperController.wallpaperCommandComplete(window);
    425         }
    426     }
    427 
    428     @Override
    429     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
    430         synchronized(mService.mWindowMap) {
    431             final long identity = Binder.clearCallingIdentity();
    432             try {
    433                 mService.onRectangleOnScreenRequested(token, rectangle);
    434             } finally {
    435                 Binder.restoreCallingIdentity(identity);
    436             }
    437         }
    438     }
    439 
    440     @Override
    441     public IWindowId getWindowId(IBinder window) {
    442         return mService.getWindowId(window);
    443     }
    444 
    445     @Override
    446     public void pokeDrawLock(IBinder window) {
    447         final long identity = Binder.clearCallingIdentity();
    448         try {
    449             mService.pokeDrawLock(this, window);
    450         } finally {
    451             Binder.restoreCallingIdentity(identity);
    452         }
    453     }
    454 
    455     @Override
    456     public void updatePointerIcon(IWindow window) {
    457         final long identity = Binder.clearCallingIdentity();
    458         try {
    459             mService.updatePointerIcon(window);
    460         } finally {
    461             Binder.restoreCallingIdentity(identity);
    462         }
    463     }
    464 
    465     @Override
    466     public void updateTapExcludeRegion(IWindow window, int regionId, int left, int top, int width,
    467             int height) {
    468         final long identity = Binder.clearCallingIdentity();
    469         try {
    470             mService.updateTapExcludeRegion(window, regionId, left, top, width, height);
    471         } finally {
    472             Binder.restoreCallingIdentity(identity);
    473         }
    474     }
    475 
    476     void windowAddedLocked(String packageName) {
    477         mPackageName = packageName;
    478         mRelayoutTag = "relayoutWindow: " + mPackageName;
    479         if (mSurfaceSession == null) {
    480             if (WindowManagerService.localLOGV) Slog.v(
    481                 TAG_WM, "First window added to " + this + ", creating SurfaceSession");
    482             mSurfaceSession = new SurfaceSession();
    483             if (SHOW_TRANSACTIONS) Slog.i(
    484                     TAG_WM, "  NEW SURFACE SESSION " + mSurfaceSession);
    485             mService.mSessions.add(this);
    486             if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
    487                 mService.dispatchNewAnimatorScaleLocked(this);
    488             }
    489         }
    490         mNumWindow++;
    491     }
    492 
    493     void windowRemovedLocked() {
    494         mNumWindow--;
    495         killSessionLocked();
    496     }
    497 
    498 
    499     void onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController,
    500             boolean visible, int type) {
    501 
    502         if (!isSystemAlertWindowType(type)) {
    503             return;
    504         }
    505 
    506         boolean changed;
    507 
    508         if (!mCanAddInternalSystemWindow) {
    509             // We want to track non-system signature apps adding alert windows so we can post an
    510             // on-going notification for the user to control their visibility.
    511             if (visible) {
    512                 changed = mAlertWindowSurfaces.add(surfaceController);
    513                 MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type, true);
    514             } else {
    515                 changed = mAlertWindowSurfaces.remove(surfaceController);
    516                 MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type, true);
    517             }
    518 
    519             if (changed) {
    520                 if (mAlertWindowSurfaces.isEmpty()) {
    521                     cancelAlertWindowNotification();
    522                 } else if (mAlertWindowNotification == null){
    523                     mAlertWindowNotification = new AlertWindowNotification(mService, mPackageName);
    524                     if (mShowingAlertWindowNotificationAllowed) {
    525                         mAlertWindowNotification.post();
    526                     }
    527                 }
    528             }
    529         }
    530 
    531         if (type != TYPE_APPLICATION_OVERLAY) {
    532             return;
    533         }
    534 
    535         if (visible) {
    536             changed = mAppOverlaySurfaces.add(surfaceController);
    537             MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type, false);
    538         } else {
    539             changed = mAppOverlaySurfaces.remove(surfaceController);
    540             MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type, false);
    541         }
    542 
    543         if (changed) {
    544             // Notify activity manager of changes to app overlay windows so it can adjust the
    545             // importance score for the process.
    546             setHasOverlayUi(!mAppOverlaySurfaces.isEmpty());
    547         }
    548     }
    549 
    550     void setShowingAlertWindowNotificationAllowed(boolean allowed) {
    551         mShowingAlertWindowNotificationAllowed = allowed;
    552         if (mAlertWindowNotification != null) {
    553             if (allowed) {
    554                 mAlertWindowNotification.post();
    555             } else {
    556                 mAlertWindowNotification.cancel(false /* deleteChannel */);
    557             }
    558         }
    559     }
    560 
    561     private void killSessionLocked() {
    562         if (mNumWindow > 0 || !mClientDead) {
    563             return;
    564         }
    565 
    566         mService.mSessions.remove(this);
    567         if (mSurfaceSession == null) {
    568             return;
    569         }
    570 
    571         if (WindowManagerService.localLOGV) Slog.v(TAG_WM, "Last window removed from " + this
    572                 + ", destroying " + mSurfaceSession);
    573         if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  KILL SURFACE SESSION " + mSurfaceSession);
    574         try {
    575             mSurfaceSession.kill();
    576         } catch (Exception e) {
    577             Slog.w(TAG_WM, "Exception thrown when killing surface session " + mSurfaceSession
    578                     + " in session " + this + ": " + e.toString());
    579         }
    580         mSurfaceSession = null;
    581         mAlertWindowSurfaces.clear();
    582         mAppOverlaySurfaces.clear();
    583         setHasOverlayUi(false);
    584         cancelAlertWindowNotification();
    585     }
    586 
    587     private void setHasOverlayUi(boolean hasOverlayUi) {
    588         mService.mH.obtainMessage(H.SET_HAS_OVERLAY_UI, mPid, hasOverlayUi ? 1 : 0).sendToTarget();
    589     }
    590 
    591     private void cancelAlertWindowNotification() {
    592         if (mAlertWindowNotification == null) {
    593             return;
    594         }
    595         mAlertWindowNotification.cancel(true /* deleteChannel */);
    596         mAlertWindowNotification = null;
    597     }
    598 
    599     void dump(PrintWriter pw, String prefix) {
    600         pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
    601                 pw.print(" mCanAddInternalSystemWindow="); pw.print(mCanAddInternalSystemWindow);
    602                 pw.print(" mAppOverlaySurfaces="); pw.print(mAppOverlaySurfaces);
    603                 pw.print(" mAlertWindowSurfaces="); pw.print(mAlertWindowSurfaces);
    604                 pw.print(" mClientDead="); pw.print(mClientDead);
    605                 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
    606         pw.print(prefix); pw.print("mPackageName="); pw.println(mPackageName);
    607     }
    608 
    609     @Override
    610     public String toString() {
    611         return mStringName;
    612     }
    613 
    614     boolean hasAlertWindowSurfaces() {
    615         return !mAlertWindowSurfaces.isEmpty();
    616     }
    617 }
    618