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.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
     20 import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
     21 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
     22 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
     23 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
     24 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
     25 
     26 import com.android.server.input.InputWindowHandle;
     27 
     28 import android.content.Context;
     29 import android.content.res.Configuration;
     30 import android.graphics.Matrix;
     31 import android.graphics.PixelFormat;
     32 import android.graphics.Rect;
     33 import android.graphics.RectF;
     34 import android.graphics.Region;
     35 import android.os.IBinder;
     36 import android.os.RemoteException;
     37 import android.util.Slog;
     38 import android.view.Gravity;
     39 import android.view.IApplicationToken;
     40 import android.view.IWindow;
     41 import android.view.InputChannel;
     42 import android.view.View;
     43 import android.view.ViewTreeObserver;
     44 import android.view.WindowManager;
     45 import android.view.WindowManagerPolicy;
     46 
     47 import java.io.PrintWriter;
     48 import java.util.ArrayList;
     49 
     50 /**
     51  * A window in the window manager.
     52  */
     53 final class WindowState implements WindowManagerPolicy.WindowState {
     54     static final String TAG = "WindowState";
     55 
     56     static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY;
     57     static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS;
     58     static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
     59     static final boolean SHOW_SURFACE_ALLOC = WindowManagerService.SHOW_SURFACE_ALLOC;
     60 
     61     final WindowManagerService mService;
     62     final WindowManagerPolicy mPolicy;
     63     final Context mContext;
     64     final Session mSession;
     65     final IWindow mClient;
     66     WindowToken mToken;
     67     WindowToken mRootToken;
     68     AppWindowToken mAppToken;
     69     AppWindowToken mTargetAppToken;
     70 
     71     // mAttrs.flags is tested in animation without being locked. If the bits tested are ever
     72     // modified they will need to be locked.
     73     final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
     74     final DeathRecipient mDeathRecipient;
     75     final WindowState mAttachedWindow;
     76     final ArrayList<WindowState> mChildWindows = new ArrayList<WindowState>();
     77     final int mBaseLayer;
     78     final int mSubLayer;
     79     final boolean mLayoutAttached;
     80     final boolean mIsImWindow;
     81     final boolean mIsWallpaper;
     82     final boolean mIsFloatingLayer;
     83     int mSeq;
     84     boolean mEnforceSizeCompat;
     85     int mViewVisibility;
     86     int mSystemUiVisibility;
     87     boolean mPolicyVisibility = true;
     88     boolean mPolicyVisibilityAfterAnim = true;
     89     boolean mAppFreezing;
     90     boolean mAttachedHidden;    // is our parent window hidden?
     91     boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
     92 
     93     /**
     94      * The window size that was requested by the application.  These are in
     95      * the application's coordinate space (without compatibility scale applied).
     96      */
     97     int mRequestedWidth;
     98     int mRequestedHeight;
     99     int mLastRequestedWidth;
    100     int mLastRequestedHeight;
    101 
    102     int mLayer;
    103     boolean mHaveFrame;
    104     boolean mObscured;
    105     boolean mTurnOnScreen;
    106 
    107     int mLayoutSeq = -1;
    108 
    109     Configuration mConfiguration = null;
    110 
    111     /**
    112      * Actual frame shown on-screen (may be modified by animation).  These
    113      * are in the screen's coordinate space (WITH the compatibility scale
    114      * applied).
    115      */
    116     final RectF mShownFrame = new RectF();
    117 
    118     /**
    119      * Insets that determine the actually visible area.  These are in the application's
    120      * coordinate space (without compatibility scale applied).
    121      */
    122     final Rect mVisibleInsets = new Rect();
    123     final Rect mLastVisibleInsets = new Rect();
    124     boolean mVisibleInsetsChanged;
    125 
    126     /**
    127      * Insets that are covered by system windows (such as the status bar) and
    128      * transient docking windows (such as the IME).  These are in the application's
    129      * coordinate space (without compatibility scale applied).
    130      */
    131     final Rect mContentInsets = new Rect();
    132     final Rect mLastContentInsets = new Rect();
    133     boolean mContentInsetsChanged;
    134 
    135     /**
    136      * Set to true if we are waiting for this window to receive its
    137      * given internal insets before laying out other windows based on it.
    138      */
    139     boolean mGivenInsetsPending;
    140 
    141     /**
    142      * These are the content insets that were given during layout for
    143      * this window, to be applied to windows behind it.
    144      */
    145     final Rect mGivenContentInsets = new Rect();
    146 
    147     /**
    148      * These are the visible insets that were given during layout for
    149      * this window, to be applied to windows behind it.
    150      */
    151     final Rect mGivenVisibleInsets = new Rect();
    152 
    153     /**
    154      * This is the given touchable area relative to the window frame, or null if none.
    155      */
    156     final Region mGivenTouchableRegion = new Region();
    157 
    158     /**
    159      * Flag indicating whether the touchable region should be adjusted by
    160      * the visible insets; if false the area outside the visible insets is
    161      * NOT touchable, so we must use those to adjust the frame during hit
    162      * tests.
    163      */
    164     int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
    165 
    166     /**
    167      * This is rectangle of the window's surface that is not covered by
    168      * system decorations.
    169      */
    170     final Rect mSystemDecorRect = new Rect();
    171     final Rect mLastSystemDecorRect = new Rect();
    172 
    173     // Current transformation being applied.
    174     float mGlobalScale=1;
    175     float mInvGlobalScale=1;
    176     float mHScale=1, mVScale=1;
    177     float mLastHScale=1, mLastVScale=1;
    178     final Matrix mTmpMatrix = new Matrix();
    179 
    180     // "Real" frame that the application sees, in display coordinate space.
    181     final Rect mFrame = new Rect();
    182     final Rect mLastFrame = new Rect();
    183     // Frame that is scaled to the application's coordinate space when in
    184     // screen size compatibility mode.
    185     final Rect mCompatFrame = new Rect();
    186 
    187     final Rect mContainingFrame = new Rect();
    188     final Rect mDisplayFrame = new Rect();
    189     final Rect mContentFrame = new Rect();
    190     final Rect mParentFrame = new Rect();
    191     final Rect mVisibleFrame = new Rect();
    192 
    193     boolean mContentChanged;
    194 
    195     // If a window showing a wallpaper: the requested offset for the
    196     // wallpaper; if a wallpaper window: the currently applied offset.
    197     float mWallpaperX = -1;
    198     float mWallpaperY = -1;
    199 
    200     // If a window showing a wallpaper: what fraction of the offset
    201     // range corresponds to a full virtual screen.
    202     float mWallpaperXStep = -1;
    203     float mWallpaperYStep = -1;
    204 
    205     // Wallpaper windows: pixels offset based on above variables.
    206     int mXOffset;
    207     int mYOffset;
    208 
    209     // This is set after IWindowSession.relayout() has been called at
    210     // least once for the window.  It allows us to detect the situation
    211     // where we don't yet have a surface, but should have one soon, so
    212     // we can give the window focus before waiting for the relayout.
    213     boolean mRelayoutCalled;
    214 
    215     // If the application has called relayout() with changes that can
    216     // impact its window's size, we need to perform a layout pass on it
    217     // even if it is not currently visible for layout.  This is set
    218     // when in that case until the layout is done.
    219     boolean mLayoutNeeded;
    220 
    221     // Currently running an exit animation?
    222     boolean mExiting;
    223 
    224     // Currently on the mDestroySurface list?
    225     boolean mDestroying;
    226 
    227     // Completely remove from window manager after exit animation?
    228     boolean mRemoveOnExit;
    229 
    230     // Set when the orientation is changing and this window has not yet
    231     // been updated for the new orientation.
    232     boolean mOrientationChanging;
    233 
    234     // Is this window now (or just being) removed?
    235     boolean mRemoved;
    236 
    237     // Temp for keeping track of windows that have been removed when
    238     // rebuilding window list.
    239     boolean mRebuilding;
    240 
    241     // Input channel and input window handle used by the input dispatcher.
    242     final InputWindowHandle mInputWindowHandle;
    243     InputChannel mInputChannel;
    244 
    245     // Used to improve performance of toString()
    246     String mStringNameCache;
    247     CharSequence mLastTitle;
    248     boolean mWasPaused;
    249 
    250     final WindowStateAnimator mWinAnimator;
    251 
    252     boolean mHasSurface = false;
    253 
    254     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
    255            WindowState attachedWindow, int seq, WindowManager.LayoutParams a,
    256            int viewVisibility) {
    257         mService = service;
    258         mSession = s;
    259         mClient = c;
    260         mToken = token;
    261         mAttrs.copyFrom(a);
    262         mViewVisibility = viewVisibility;
    263         mPolicy = mService.mPolicy;
    264         mContext = mService.mContext;
    265         DeathRecipient deathRecipient = new DeathRecipient();
    266         mSeq = seq;
    267         mEnforceSizeCompat = (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
    268         if (WindowManagerService.localLOGV) Slog.v(
    269             TAG, "Window " + this + " client=" + c.asBinder()
    270             + " token=" + token + " (" + mAttrs.token + ")");
    271         try {
    272             c.asBinder().linkToDeath(deathRecipient, 0);
    273         } catch (RemoteException e) {
    274             mDeathRecipient = null;
    275             mAttachedWindow = null;
    276             mLayoutAttached = false;
    277             mIsImWindow = false;
    278             mIsWallpaper = false;
    279             mIsFloatingLayer = false;
    280             mBaseLayer = 0;
    281             mSubLayer = 0;
    282             mInputWindowHandle = null;
    283             mWinAnimator = null;
    284             return;
    285         }
    286         mDeathRecipient = deathRecipient;
    287 
    288         if ((mAttrs.type >= FIRST_SUB_WINDOW &&
    289                 mAttrs.type <= LAST_SUB_WINDOW)) {
    290             // The multiplier here is to reserve space for multiple
    291             // windows in the same type layer.
    292             mBaseLayer = mPolicy.windowTypeToLayerLw(
    293                     attachedWindow.mAttrs.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER
    294                     + WindowManagerService.TYPE_LAYER_OFFSET;
    295             mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
    296             mAttachedWindow = attachedWindow;
    297             if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow);
    298             mAttachedWindow.mChildWindows.add(this);
    299             mLayoutAttached = mAttrs.type !=
    300                     WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
    301             mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
    302                     || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
    303             mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
    304             mIsFloatingLayer = mIsImWindow || mIsWallpaper;
    305         } else {
    306             // The multiplier here is to reserve space for multiple
    307             // windows in the same type layer.
    308             mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
    309                     * WindowManagerService.TYPE_LAYER_MULTIPLIER
    310                     + WindowManagerService.TYPE_LAYER_OFFSET;
    311             mSubLayer = 0;
    312             mAttachedWindow = null;
    313             mLayoutAttached = false;
    314             mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
    315                     || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
    316             mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
    317             mIsFloatingLayer = mIsImWindow || mIsWallpaper;
    318         }
    319 
    320         mWinAnimator = new WindowStateAnimator(service, this, mAttachedWindow);
    321         mWinAnimator.mAlpha = a.alpha;
    322 
    323         WindowState appWin = this;
    324         while (appWin.mAttachedWindow != null) {
    325             appWin = appWin.mAttachedWindow;
    326         }
    327         WindowToken appToken = appWin.mToken;
    328         while (appToken.appWindowToken == null) {
    329             WindowToken parent = mService.mTokenMap.get(appToken.token);
    330             if (parent == null || appToken == parent) {
    331                 break;
    332             }
    333             appToken = parent;
    334         }
    335         mRootToken = appToken;
    336         mAppToken = appToken.appWindowToken;
    337 
    338         mRequestedWidth = 0;
    339         mRequestedHeight = 0;
    340         mLastRequestedWidth = 0;
    341         mLastRequestedHeight = 0;
    342         mXOffset = 0;
    343         mYOffset = 0;
    344         mLayer = 0;
    345         mInputWindowHandle = new InputWindowHandle(
    346                 mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
    347     }
    348 
    349     void attach() {
    350         if (WindowManagerService.localLOGV) Slog.v(
    351             TAG, "Attaching " + this + " token=" + mToken
    352             + ", list=" + mToken.windows);
    353         mSession.windowAddedLocked();
    354     }
    355 
    356     @Override
    357     public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
    358         mHaveFrame = true;
    359 
    360         final Rect container = mContainingFrame;
    361         container.set(pf);
    362 
    363         final Rect display = mDisplayFrame;
    364         display.set(df);
    365 
    366         final int pw = container.right - container.left;
    367         final int ph = container.bottom - container.top;
    368 
    369         int w,h;
    370         if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0) {
    371             if (mAttrs.width < 0) {
    372                 w = pw;
    373             } else if (mEnforceSizeCompat) {
    374                 w = (int)(mAttrs.width * mGlobalScale + .5f);
    375             } else {
    376                 w = mAttrs.width;
    377             }
    378             if (mAttrs.height < 0) {
    379                 h = ph;
    380             } else if (mEnforceSizeCompat) {
    381                 h = (int)(mAttrs.height * mGlobalScale + .5f);
    382             } else {
    383                 h = mAttrs.height;
    384             }
    385         } else {
    386             if (mAttrs.width == WindowManager.LayoutParams.MATCH_PARENT) {
    387                 w = pw;
    388             } else if (mEnforceSizeCompat) {
    389                 w = (int)(mRequestedWidth * mGlobalScale + .5f);
    390             } else {
    391                 w = mRequestedWidth;
    392             }
    393             if (mAttrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
    394                 h = ph;
    395             } else if (mEnforceSizeCompat) {
    396                 h = (int)(mRequestedHeight * mGlobalScale + .5f);
    397             } else {
    398                 h = mRequestedHeight;
    399             }
    400         }
    401 
    402         if (!mParentFrame.equals(pf)) {
    403             //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame
    404             //        + " to " + pf);
    405             mParentFrame.set(pf);
    406             mContentChanged = true;
    407         }
    408         if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
    409             mLastRequestedWidth = mRequestedWidth;
    410             mLastRequestedHeight = mRequestedHeight;
    411             mContentChanged = true;
    412         }
    413 
    414         final Rect content = mContentFrame;
    415         content.set(cf);
    416 
    417         final Rect visible = mVisibleFrame;
    418         visible.set(vf);
    419 
    420         final Rect frame = mFrame;
    421         final int fw = frame.width();
    422         final int fh = frame.height();
    423 
    424         //System.out.println("In: w=" + w + " h=" + h + " container=" +
    425         //                   container + " x=" + mAttrs.x + " y=" + mAttrs.y);
    426 
    427         float x, y;
    428         if (mEnforceSizeCompat) {
    429             x = mAttrs.x * mGlobalScale;
    430             y = mAttrs.y * mGlobalScale;
    431         } else {
    432             x = mAttrs.x;
    433             y = mAttrs.y;
    434         }
    435 
    436         Gravity.apply(mAttrs.gravity, w, h, container,
    437                 (int) (x + mAttrs.horizontalMargin * pw),
    438                 (int) (y + mAttrs.verticalMargin * ph), frame);
    439 
    440         //System.out.println("Out: " + mFrame);
    441 
    442         // Now make sure the window fits in the overall display.
    443         Gravity.applyDisplay(mAttrs.gravity, df, frame);
    444 
    445         // Make sure the system, content and visible frames are inside of the
    446         // final window frame.
    447         if (content.left < frame.left) content.left = frame.left;
    448         if (content.top < frame.top) content.top = frame.top;
    449         if (content.right > frame.right) content.right = frame.right;
    450         if (content.bottom > frame.bottom) content.bottom = frame.bottom;
    451         if (visible.left < frame.left) visible.left = frame.left;
    452         if (visible.top < frame.top) visible.top = frame.top;
    453         if (visible.right > frame.right) visible.right = frame.right;
    454         if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
    455 
    456         final Rect contentInsets = mContentInsets;
    457         contentInsets.left = content.left-frame.left;
    458         contentInsets.top = content.top-frame.top;
    459         contentInsets.right = frame.right-content.right;
    460         contentInsets.bottom = frame.bottom-content.bottom;
    461 
    462         final Rect visibleInsets = mVisibleInsets;
    463         visibleInsets.left = visible.left-frame.left;
    464         visibleInsets.top = visible.top-frame.top;
    465         visibleInsets.right = frame.right-visible.right;
    466         visibleInsets.bottom = frame.bottom-visible.bottom;
    467 
    468         mCompatFrame.set(frame);
    469         if (mEnforceSizeCompat) {
    470             // If there is a size compatibility scale being applied to the
    471             // window, we need to apply this to its insets so that they are
    472             // reported to the app in its coordinate space.
    473             contentInsets.scale(mInvGlobalScale);
    474             visibleInsets.scale(mInvGlobalScale);
    475 
    476             // Also the scaled frame that we report to the app needs to be
    477             // adjusted to be in its coordinate space.
    478             mCompatFrame.scale(mInvGlobalScale);
    479         }
    480 
    481         if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
    482             mService.updateWallpaperOffsetLocked(this,
    483                     mService.mAppDisplayWidth, mService.mAppDisplayHeight, false);
    484         }
    485 
    486         if (WindowManagerService.localLOGV) {
    487             //if ("com.google.android.youtube".equals(mAttrs.packageName)
    488             //        && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
    489                 Slog.v(TAG, "Resolving (mRequestedWidth="
    490                         + mRequestedWidth + ", mRequestedheight="
    491                         + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
    492                         + "): frame=" + mFrame.toShortString()
    493                         + " ci=" + contentInsets.toShortString()
    494                         + " vi=" + visibleInsets.toShortString());
    495             //}
    496         }
    497     }
    498 
    499     @Override
    500     public Rect getFrameLw() {
    501         return mFrame;
    502     }
    503 
    504     @Override
    505     public RectF getShownFrameLw() {
    506         return mShownFrame;
    507     }
    508 
    509     @Override
    510     public Rect getDisplayFrameLw() {
    511         return mDisplayFrame;
    512     }
    513 
    514     @Override
    515     public Rect getContentFrameLw() {
    516         return mContentFrame;
    517     }
    518 
    519     @Override
    520     public Rect getVisibleFrameLw() {
    521         return mVisibleFrame;
    522     }
    523 
    524     @Override
    525     public boolean getGivenInsetsPendingLw() {
    526         return mGivenInsetsPending;
    527     }
    528 
    529     @Override
    530     public Rect getGivenContentInsetsLw() {
    531         return mGivenContentInsets;
    532     }
    533 
    534     @Override
    535     public Rect getGivenVisibleInsetsLw() {
    536         return mGivenVisibleInsets;
    537     }
    538 
    539     @Override
    540     public WindowManager.LayoutParams getAttrs() {
    541         return mAttrs;
    542     }
    543 
    544     public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) {
    545         int index = -1;
    546         WindowState ws = this;
    547         while (true) {
    548             if ((ws.mAttrs.privateFlags
    549                     & WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY) != 0) {
    550                 return (ws.mAttrs.flags & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0;
    551             }
    552             // If we reached the bottom of the range of windows we are considering,
    553             // assume no menu is needed.
    554             if (ws == bottom) {
    555                 return false;
    556             }
    557             // The current window hasn't specified whether menu key is needed;
    558             // look behind it.
    559             // First, we may need to determine the starting position.
    560             if (index < 0) {
    561                 index = mService.mWindows.indexOf(ws);
    562             }
    563             index--;
    564             if (index < 0) {
    565                 return false;
    566             }
    567             ws = mService.mWindows.get(index);
    568         }
    569     }
    570 
    571     public int getSystemUiVisibility() {
    572         return mSystemUiVisibility;
    573     }
    574 
    575     public int getSurfaceLayer() {
    576         return mLayer;
    577     }
    578 
    579     public IApplicationToken getAppToken() {
    580         return mAppToken != null ? mAppToken.appToken : null;
    581     }
    582 
    583     public long getInputDispatchingTimeoutNanos() {
    584         return mAppToken != null
    585                 ? mAppToken.inputDispatchingTimeoutNanos
    586                 : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
    587     }
    588 
    589     public boolean hasAppShownWindows() {
    590         return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed);
    591     }
    592 
    593     boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
    594         if (dsdx < .99999f || dsdx > 1.00001f) return false;
    595         if (dtdy < .99999f || dtdy > 1.00001f) return false;
    596         if (dtdx < -.000001f || dtdx > .000001f) return false;
    597         if (dsdy < -.000001f || dsdy > .000001f) return false;
    598         return true;
    599     }
    600 
    601     void prelayout() {
    602         if (mEnforceSizeCompat) {
    603             mGlobalScale = mService.mCompatibleScreenScale;
    604             mInvGlobalScale = 1/mGlobalScale;
    605         } else {
    606             mGlobalScale = mInvGlobalScale = 1;
    607         }
    608     }
    609 
    610     /**
    611      * Is this window visible?  It is not visible if there is no
    612      * surface, or we are in the process of running an exit animation
    613      * that will remove the surface, or its app token has been hidden.
    614      */
    615     public boolean isVisibleLw() {
    616         final AppWindowToken atoken = mAppToken;
    617         return mHasSurface && mPolicyVisibility && !mAttachedHidden
    618                 && (atoken == null || !atoken.hiddenRequested)
    619                 && !mExiting && !mDestroying;
    620     }
    621 
    622     /**
    623      * Like {@link #isVisibleLw}, but also counts a window that is currently
    624      * "hidden" behind the keyguard as visible.  This allows us to apply
    625      * things like window flags that impact the keyguard.
    626      * XXX I am starting to think we need to have ANOTHER visibility flag
    627      * for this "hidden behind keyguard" state rather than overloading
    628      * mPolicyVisibility.  Ungh.
    629      */
    630     public boolean isVisibleOrBehindKeyguardLw() {
    631         if (mRootToken.waitingToShow &&
    632                 mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
    633             return false;
    634         }
    635         final AppWindowToken atoken = mAppToken;
    636         final boolean animating = atoken != null
    637                 ? (atoken.mAppAnimator.animation != null) : false;
    638         return mHasSurface && !mDestroying && !mExiting
    639                 && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
    640                 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
    641                                 && !mRootToken.hidden)
    642                         || mWinAnimator.mAnimation != null || animating);
    643     }
    644 
    645     /**
    646      * Is this window visible, ignoring its app token?  It is not visible
    647      * if there is no surface, or we are in the process of running an exit animation
    648      * that will remove the surface.
    649      */
    650     public boolean isWinVisibleLw() {
    651         final AppWindowToken atoken = mAppToken;
    652         return mHasSurface && mPolicyVisibility && !mAttachedHidden
    653                 && (atoken == null || !atoken.hiddenRequested || atoken.mAppAnimator.animating)
    654                 && !mExiting && !mDestroying;
    655     }
    656 
    657     /**
    658      * The same as isVisible(), but follows the current hidden state of
    659      * the associated app token, not the pending requested hidden state.
    660      */
    661     boolean isVisibleNow() {
    662         return mHasSurface && mPolicyVisibility && !mAttachedHidden
    663                 && !mRootToken.hidden && !mExiting && !mDestroying;
    664     }
    665 
    666     /**
    667      * Can this window possibly be a drag/drop target?  The test here is
    668      * a combination of the above "visible now" with the check that the
    669      * Input Manager uses when discarding windows from input consideration.
    670      */
    671     boolean isPotentialDragTarget() {
    672         return isVisibleNow() && !mRemoved
    673                 && mInputChannel != null && mInputWindowHandle != null;
    674     }
    675 
    676     /**
    677      * Same as isVisible(), but we also count it as visible between the
    678      * call to IWindowSession.add() and the first relayout().
    679      */
    680     boolean isVisibleOrAdding() {
    681         final AppWindowToken atoken = mAppToken;
    682         return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
    683                 && mPolicyVisibility && !mAttachedHidden
    684                 && (atoken == null || !atoken.hiddenRequested)
    685                 && !mExiting && !mDestroying;
    686     }
    687 
    688     /**
    689      * Is this window currently on-screen?  It is on-screen either if it
    690      * is visible or it is currently running an animation before no longer
    691      * being visible.
    692      */
    693     boolean isOnScreen() {
    694         if (!mHasSurface || !mPolicyVisibility || mDestroying) {
    695             return false;
    696         }
    697         final AppWindowToken atoken = mAppToken;
    698         if (atoken != null) {
    699             return ((!mAttachedHidden && !atoken.hiddenRequested)
    700                             || mWinAnimator.mAnimation != null || atoken.mAppAnimator.animation != null);
    701         }
    702         return !mAttachedHidden || mWinAnimator.mAnimation != null;
    703     }
    704 
    705     /**
    706      * Like isOnScreen(), but we don't return true if the window is part
    707      * of a transition that has not yet been started.
    708      */
    709     boolean isReadyForDisplay() {
    710         if (mRootToken.waitingToShow &&
    711                 mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
    712             return false;
    713         }
    714         return mHasSurface && mPolicyVisibility && !mDestroying
    715                 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
    716                                 && !mRootToken.hidden)
    717                         || mWinAnimator.mAnimation != null
    718                         || ((mAppToken != null) && (mAppToken.mAppAnimator.animation != null)));
    719     }
    720 
    721     /**
    722      * Like isReadyForDisplay(), but ignores any force hiding of the window due
    723      * to the keyguard.
    724      */
    725     boolean isReadyForDisplayIgnoringKeyguard() {
    726         if (mRootToken.waitingToShow &&
    727                 mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
    728             return false;
    729         }
    730         final AppWindowToken atoken = mAppToken;
    731         if (atoken == null && !mPolicyVisibility) {
    732             // If this is not an app window, and the policy has asked to force
    733             // hide, then we really do want to hide.
    734             return false;
    735         }
    736         return mHasSurface && !mDestroying
    737                 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
    738                                 && !mRootToken.hidden)
    739                         || mWinAnimator.mAnimation != null
    740                         || ((atoken != null) && (atoken.mAppAnimator.animation != null)
    741                                 && !mWinAnimator.isDummyAnimation()));
    742     }
    743 
    744     /**
    745      * Like isOnScreen, but returns false if the surface hasn't yet
    746      * been drawn.
    747      */
    748     public boolean isDisplayedLw() {
    749         final AppWindowToken atoken = mAppToken;
    750         return isDrawnLw() && mPolicyVisibility
    751             && ((!mAttachedHidden &&
    752                     (atoken == null || !atoken.hiddenRequested))
    753                     || mWinAnimator.mAnimating);
    754     }
    755 
    756     /**
    757      * Return true if this window (or a window it is attached to, but not
    758      * considering its app token) is currently animating.
    759      */
    760     public boolean isAnimatingLw() {
    761         return mWinAnimator.mAnimation != null;
    762     }
    763 
    764     public boolean isGoneForLayoutLw() {
    765         final AppWindowToken atoken = mAppToken;
    766         return mViewVisibility == View.GONE
    767                 || !mRelayoutCalled
    768                 || (atoken == null && mRootToken.hidden)
    769                 || (atoken != null && (atoken.hiddenRequested || atoken.hidden))
    770                 || mAttachedHidden
    771                 || mExiting || mDestroying;
    772     }
    773 
    774     /**
    775      * Returns true if the window has a surface that it has drawn a
    776      * complete UI in to.
    777      */
    778     public boolean isDrawnLw() {
    779         return mHasSurface && !mDestroying &&
    780                 (mWinAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW
    781                 || mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN);
    782     }
    783 
    784     /**
    785      * Return true if the window is opaque and fully drawn.  This indicates
    786      * it may obscure windows behind it.
    787      */
    788     boolean isOpaqueDrawn() {
    789         return (mAttrs.format == PixelFormat.OPAQUE
    790                         || mAttrs.type == TYPE_WALLPAPER)
    791                 && isDrawnLw() && mWinAnimator.mAnimation == null
    792                 && (mAppToken == null || mAppToken.mAppAnimator.animation == null);
    793     }
    794 
    795     /**
    796      * Return whether this window is wanting to have a translation
    797      * animation applied to it for an in-progress move.  (Only makes
    798      * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
    799      */
    800     boolean shouldAnimateMove() {
    801         return mContentChanged && !mExiting && !mWinAnimator.mLastHidden && mService.okToDisplay()
    802                 && (mFrame.top != mLastFrame.top
    803                         || mFrame.left != mLastFrame.left)
    804                 && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove());
    805     }
    806 
    807     boolean isFullscreen(int screenWidth, int screenHeight) {
    808         return mFrame.left <= 0 && mFrame.top <= 0 &&
    809                 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
    810     }
    811 
    812     void removeLocked() {
    813         disposeInputChannel();
    814 
    815         if (mAttachedWindow != null) {
    816             if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow);
    817             mAttachedWindow.mChildWindows.remove(this);
    818         }
    819         mWinAnimator.destroyDeferredSurfaceLocked();
    820         mWinAnimator.destroySurfaceLocked();
    821         mSession.windowRemovedLocked();
    822         try {
    823             mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
    824         } catch (RuntimeException e) {
    825             // Ignore if it has already been removed (usually because
    826             // we are doing this as part of processing a death note.)
    827         }
    828     }
    829 
    830     void setInputChannel(InputChannel inputChannel) {
    831         if (mInputChannel != null) {
    832             throw new IllegalStateException("Window already has an input channel.");
    833         }
    834 
    835         mInputChannel = inputChannel;
    836         mInputWindowHandle.inputChannel = inputChannel;
    837     }
    838 
    839     void disposeInputChannel() {
    840         if (mInputChannel != null) {
    841             mService.mInputManager.unregisterInputChannel(mInputChannel);
    842 
    843             mInputChannel.dispose();
    844             mInputChannel = null;
    845         }
    846 
    847         mInputWindowHandle.inputChannel = null;
    848     }
    849 
    850     private class DeathRecipient implements IBinder.DeathRecipient {
    851         public void binderDied() {
    852             try {
    853                 synchronized(mService.mWindowMap) {
    854                     WindowState win = mService.windowForClientLocked(mSession, mClient, false);
    855                     Slog.i(TAG, "WIN DEATH: " + win);
    856                     if (win != null) {
    857                         mService.removeWindowLocked(mSession, win);
    858                     }
    859                 }
    860             } catch (IllegalArgumentException ex) {
    861                 // This will happen if the window has already been
    862                 // removed.
    863             }
    864         }
    865     }
    866 
    867     /** Returns true if this window desires key events.
    868      * TODO(cmautner): Is this the same as {@link WindowManagerService#canBeImeTarget}
    869      */
    870     public final boolean canReceiveKeys() {
    871         return     isVisibleOrAdding()
    872                 && (mViewVisibility == View.VISIBLE)
    873                 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
    874     }
    875 
    876     @Override
    877     public boolean hasDrawnLw() {
    878         return mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN;
    879     }
    880 
    881     @Override
    882     public boolean showLw(boolean doAnimation) {
    883         return showLw(doAnimation, true);
    884     }
    885 
    886     boolean showLw(boolean doAnimation, boolean requestAnim) {
    887         if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
    888             // Already showing.
    889             return false;
    890         }
    891         if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
    892         if (doAnimation) {
    893             if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
    894                     + mPolicyVisibility + " mAnimation=" + mWinAnimator.mAnimation);
    895             if (!mService.okToDisplay()) {
    896                 doAnimation = false;
    897             } else if (mPolicyVisibility && mWinAnimator.mAnimation == null) {
    898                 // Check for the case where we are currently visible and
    899                 // not animating; we do not want to do animation at such a
    900                 // point to become visible when we already are.
    901                 doAnimation = false;
    902             }
    903         }
    904         mPolicyVisibility = true;
    905         mPolicyVisibilityAfterAnim = true;
    906         if (doAnimation) {
    907             mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_ENTER, true);
    908         }
    909         if (requestAnim) {
    910             mService.scheduleAnimationLocked();
    911         }
    912         return true;
    913     }
    914 
    915     @Override
    916     public boolean hideLw(boolean doAnimation) {
    917         return hideLw(doAnimation, true);
    918     }
    919 
    920     boolean hideLw(boolean doAnimation, boolean requestAnim) {
    921         if (doAnimation) {
    922             if (!mService.okToDisplay()) {
    923                 doAnimation = false;
    924             }
    925         }
    926         boolean current = doAnimation ? mPolicyVisibilityAfterAnim
    927                 : mPolicyVisibility;
    928         if (!current) {
    929             // Already hiding.
    930             return false;
    931         }
    932         if (doAnimation) {
    933             mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, false);
    934             if (mWinAnimator.mAnimation == null) {
    935                 doAnimation = false;
    936             }
    937         }
    938         if (doAnimation) {
    939             mPolicyVisibilityAfterAnim = false;
    940         } else {
    941             if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
    942             mPolicyVisibilityAfterAnim = false;
    943             mPolicyVisibility = false;
    944             // Window is no longer visible -- make sure if we were waiting
    945             // for it to be displayed before enabling the display, that
    946             // we allow the display to be enabled now.
    947             mService.enableScreenIfNeededLocked();
    948             if (mService.mCurrentFocus == this) {
    949                 mService.mFocusMayChange = true;
    950             }
    951         }
    952         if (requestAnim) {
    953             mService.scheduleAnimationLocked();
    954         }
    955         return true;
    956     }
    957 
    958     @Override
    959     public boolean isAlive() {
    960         return mClient.asBinder().isBinderAlive();
    961     }
    962 
    963     private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
    964         outRegion.set(
    965                 frame.left + inset.left, frame.top + inset.top,
    966                 frame.right - inset.right, frame.bottom - inset.bottom);
    967     }
    968 
    969     public void getTouchableRegion(Region outRegion) {
    970         final Rect frame = mFrame;
    971         switch (mTouchableInsets) {
    972             default:
    973             case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
    974                 outRegion.set(frame);
    975                 break;
    976             case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT:
    977                 applyInsets(outRegion, frame, mGivenContentInsets);
    978                 break;
    979             case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE:
    980                 applyInsets(outRegion, frame, mGivenVisibleInsets);
    981                 break;
    982             case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: {
    983                 final Region givenTouchableRegion = mGivenTouchableRegion;
    984                 outRegion.set(givenTouchableRegion);
    985                 outRegion.translate(frame.left, frame.top);
    986                 break;
    987             }
    988         }
    989     }
    990 
    991     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
    992         pw.print(prefix); pw.print("mSession="); pw.print(mSession);
    993                 pw.print(" mClient="); pw.println(mClient.asBinder());
    994         pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
    995         pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
    996                 pw.print(" h="); pw.print(mRequestedHeight);
    997                 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
    998         if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
    999             pw.print(prefix); pw.print("LastRequested w="); pw.print(mLastRequestedWidth);
   1000                     pw.print(" h="); pw.println(mLastRequestedHeight);
   1001         }
   1002         if (mAttachedWindow != null || mLayoutAttached) {
   1003             pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
   1004                     pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
   1005         }
   1006         if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
   1007             pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
   1008                     pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
   1009                     pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
   1010                     pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
   1011         }
   1012         if (dumpAll) {
   1013             pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
   1014                     pw.print(" mSubLayer="); pw.print(mSubLayer);
   1015                     pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
   1016                     pw.print((mTargetAppToken != null ?
   1017                             mTargetAppToken.mAppAnimator.animLayerAdjustment
   1018                           : (mAppToken != null ? mAppToken.mAppAnimator.animLayerAdjustment : 0)));
   1019                     pw.print("="); pw.print(mWinAnimator.mAnimLayer);
   1020                     pw.print(" mLastLayer="); pw.println(mWinAnimator.mLastLayer);
   1021         }
   1022         if (dumpAll) {
   1023             pw.print(prefix); pw.print("mToken="); pw.println(mToken);
   1024             pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
   1025             if (mAppToken != null) {
   1026                 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
   1027             }
   1028             if (mTargetAppToken != null) {
   1029                 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
   1030             }
   1031             pw.print(prefix); pw.print("mViewVisibility=0x");
   1032             pw.print(Integer.toHexString(mViewVisibility));
   1033             pw.print(" mHaveFrame="); pw.print(mHaveFrame);
   1034             pw.print(" mObscured="); pw.println(mObscured);
   1035             pw.print(prefix); pw.print("mSeq="); pw.print(mSeq);
   1036             pw.print(" mSystemUiVisibility=0x");
   1037             pw.println(Integer.toHexString(mSystemUiVisibility));
   1038         }
   1039         if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
   1040             pw.print(prefix); pw.print("mPolicyVisibility=");
   1041                     pw.print(mPolicyVisibility);
   1042                     pw.print(" mPolicyVisibilityAfterAnim=");
   1043                     pw.print(mPolicyVisibilityAfterAnim);
   1044                     pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
   1045         }
   1046         if (!mRelayoutCalled || mLayoutNeeded) {
   1047             pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled);
   1048                     pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded);
   1049         }
   1050         if (mXOffset != 0 || mYOffset != 0) {
   1051             pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
   1052                     pw.print(" y="); pw.println(mYOffset);
   1053         }
   1054         if (dumpAll) {
   1055             pw.print(prefix); pw.print("mGivenContentInsets=");
   1056                     mGivenContentInsets.printShortString(pw);
   1057                     pw.print(" mGivenVisibleInsets=");
   1058                     mGivenVisibleInsets.printShortString(pw);
   1059                     pw.println();
   1060             if (mTouchableInsets != 0 || mGivenInsetsPending) {
   1061                 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
   1062                         pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
   1063             }
   1064             pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
   1065         }
   1066         pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
   1067                 pw.print(" mShownFrame="); mShownFrame.printShortString(pw); pw.println();
   1068         if (dumpAll) {
   1069             pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
   1070                     pw.print(" last="); mLastFrame.printShortString(pw);
   1071                     pw.println();
   1072             pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw);
   1073                     pw.print(" last="); mLastSystemDecorRect.printShortString(pw);
   1074                     pw.println();
   1075         }
   1076         if (mEnforceSizeCompat) {
   1077             pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw);
   1078                     pw.println();
   1079         }
   1080         if (dumpAll) {
   1081             pw.print(prefix); pw.print("Frames: containing=");
   1082                     mContainingFrame.printShortString(pw);
   1083                     pw.print(" parent="); mParentFrame.printShortString(pw);
   1084                     pw.print(" display="); mDisplayFrame.printShortString(pw);
   1085                     pw.println();
   1086             pw.print(prefix); pw.print("    content="); mContentFrame.printShortString(pw);
   1087                     pw.print(" visible="); mVisibleFrame.printShortString(pw);
   1088                     pw.println();
   1089             pw.print(prefix); pw.print("Cur insets: content=");
   1090                     mContentInsets.printShortString(pw);
   1091                     pw.print(" visible="); mVisibleInsets.printShortString(pw);
   1092                     pw.println();
   1093             pw.print(prefix); pw.print("Lst insets: content=");
   1094                     mLastContentInsets.printShortString(pw);
   1095                     pw.print(" visible="); mLastVisibleInsets.printShortString(pw);
   1096                     pw.println();
   1097         }
   1098         mWinAnimator.dump(pw, prefix, dumpAll);
   1099         if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
   1100             pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
   1101                     pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
   1102                     pw.print(" mDestroying="); pw.print(mDestroying);
   1103                     pw.print(" mRemoved="); pw.println(mRemoved);
   1104         }
   1105         if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
   1106             pw.print(prefix); pw.print("mOrientationChanging=");
   1107                     pw.print(mOrientationChanging);
   1108                     pw.print(" mAppFreezing="); pw.print(mAppFreezing);
   1109                     pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
   1110         }
   1111         if (mHScale != 1 || mVScale != 1) {
   1112             pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
   1113                     pw.print(" mVScale="); pw.println(mVScale);
   1114         }
   1115         if (mWallpaperX != -1 || mWallpaperY != -1) {
   1116             pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
   1117                     pw.print(" mWallpaperY="); pw.println(mWallpaperY);
   1118         }
   1119         if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
   1120             pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
   1121                     pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
   1122         }
   1123     }
   1124 
   1125     String makeInputChannelName() {
   1126         return Integer.toHexString(System.identityHashCode(this))
   1127             + " " + mAttrs.getTitle();
   1128     }
   1129 
   1130     @Override
   1131     public String toString() {
   1132         if (mStringNameCache == null || mLastTitle != mAttrs.getTitle()
   1133                 || mWasPaused != mToken.paused) {
   1134             mLastTitle = mAttrs.getTitle();
   1135             mWasPaused = mToken.paused;
   1136             mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
   1137                     + " " + mLastTitle + " paused=" + mWasPaused + "}";
   1138         }
   1139         return mStringNameCache;
   1140     }
   1141 }
   1142