Home | History | Annotate | Download | only in wm
      1 /*
      2  * Copyright (C) 2015 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 com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
     20 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
     21 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
     22 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
     23 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
     24 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
     25 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
     26 import static android.view.Surface.SCALING_MODE_FREEZE;
     27 import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW;
     28 
     29 import android.graphics.PixelFormat;
     30 import android.graphics.Point;
     31 import android.graphics.PointF;
     32 import android.graphics.Rect;
     33 import android.graphics.Region;
     34 import android.os.IBinder;
     35 import android.os.Debug;
     36 import android.view.Surface;
     37 import android.view.SurfaceControl;
     38 import android.view.SurfaceSession;
     39 import android.view.WindowContentFrameStats;
     40 import android.view.Surface.OutOfResourcesException;
     41 
     42 import android.util.Slog;
     43 
     44 import java.io.PrintWriter;
     45 import java.util.ArrayList;
     46 
     47 class WindowSurfaceController {
     48     static final String TAG = TAG_WITH_CLASS_NAME ? "WindowSurfaceController" : TAG_WM;
     49 
     50     final WindowStateAnimator mAnimator;
     51 
     52     private SurfaceControl mSurfaceControl;
     53 
     54     private boolean mSurfaceShown = false;
     55     private float mSurfaceX = 0;
     56     private float mSurfaceY = 0;
     57     private float mSurfaceW = 0;
     58     private float mSurfaceH = 0;
     59 
     60     private float mSurfaceAlpha = 0;
     61 
     62     private int mSurfaceLayer = 0;
     63 
     64     // Surface flinger doesn't support crop rectangles where width or height is non-positive.
     65     // However, we need to somehow handle the situation where the cropping would completely hide
     66     // the window. We achieve this by explicitly hiding the surface and not letting it be shown.
     67     private boolean mHiddenForCrop = false;
     68 
     69     // Initially a surface is hidden after just being created.
     70     private boolean mHiddenForOtherReasons = true;
     71     private final String title;
     72 
     73     public WindowSurfaceController(SurfaceSession s,
     74             String name, int w, int h, int format, int flags, WindowStateAnimator animator) {
     75         mAnimator = animator;
     76 
     77         mSurfaceW = w;
     78         mSurfaceH = h;
     79 
     80         title = name;
     81 
     82         // For opaque child windows placed under parent windows,
     83         // we use a special SurfaceControl which mirrors commands
     84         // to a black-out layer placed one Z-layer below the surface.
     85         // This prevents holes to whatever app/wallpaper is underneath.
     86         if (animator.mWin.isChildWindow() &&
     87                 animator.mWin.mSubLayer < 0 &&
     88                 animator.mWin.mAppToken != null) {
     89             mSurfaceControl = new SurfaceControlWithBackground(s,
     90                     name, w, h, format, flags, animator.mWin.mAppToken);
     91         } else if (DEBUG_SURFACE_TRACE) {
     92             mSurfaceControl = new SurfaceTrace(
     93                     s, name, w, h, format, flags);
     94         } else {
     95             mSurfaceControl = new SurfaceControl(
     96                     s, name, w, h, format, flags);
     97         }
     98     }
     99 
    100 
    101     void logSurface(String msg, RuntimeException where) {
    102         String str = "  SURFACE " + msg + ": " + title;
    103         if (where != null) {
    104             Slog.i(TAG, str, where);
    105         } else {
    106             Slog.i(TAG, str);
    107         }
    108     }
    109 
    110     void hideInTransaction(String reason) {
    111         if (SHOW_TRANSACTIONS) logSurface("HIDE ( " + reason + " )", null);
    112         mHiddenForOtherReasons = true;
    113 
    114         mAnimator.destroyPreservedSurfaceLocked();
    115         updateVisibility();
    116     }
    117 
    118     private void hideSurface() {
    119         if (mSurfaceControl != null) {
    120             mSurfaceShown = false;
    121             try {
    122                 mSurfaceControl.hide();
    123             } catch (RuntimeException e) {
    124                 Slog.w(TAG, "Exception hiding surface in " + this);
    125             }
    126         }
    127     }
    128 
    129     void setPositionAndLayer(float left, float top, int layerStack, int layer) {
    130         SurfaceControl.openTransaction();
    131         try {
    132             mSurfaceX = left;
    133             mSurfaceY = top;
    134 
    135             try {
    136                 if (SHOW_TRANSACTIONS) logSurface(
    137                         "POS (setPositionAndLayer) @ (" + left + "," + top + ")", null);
    138                 mSurfaceControl.setPosition(left, top);
    139                 mSurfaceControl.setLayerStack(layerStack);
    140 
    141                 mSurfaceControl.setLayer(layer);
    142                 mSurfaceControl.setAlpha(0);
    143                 mSurfaceShown = false;
    144             } catch (RuntimeException e) {
    145                 Slog.w(TAG, "Error creating surface in " + this, e);
    146                 mAnimator.reclaimSomeSurfaceMemory("create-init", true);
    147             }
    148         } finally {
    149             SurfaceControl.closeTransaction();
    150             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
    151                     "<<< CLOSE TRANSACTION setPositionAndLayer");
    152         }
    153     }
    154 
    155     void destroyInTransaction() {
    156         if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    157             Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(8));
    158         }
    159         try {
    160             if (mSurfaceControl != null) {
    161                 mSurfaceControl.destroy();
    162             }
    163         } catch (RuntimeException e) {
    164             Slog.w(TAG, "Error destroying surface in: " + this, e);
    165         } finally {
    166             mSurfaceShown = false;
    167             mSurfaceControl = null;
    168         }
    169     }
    170 
    171     void disconnectInTransaction() {
    172         if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    173             Slog.i(TAG, "Disconnecting client: " + this);
    174         }
    175 
    176         try {
    177             if (mSurfaceControl != null) {
    178                 mSurfaceControl.disconnect();
    179             }
    180         } catch (RuntimeException e) {
    181             Slog.w(TAG, "Error disconnecting surface in: " + this, e);
    182         }
    183     }
    184 
    185     void setCropInTransaction(Rect clipRect, boolean recoveringMemory) {
    186         if (SHOW_TRANSACTIONS) logSurface(
    187                 "CROP " + clipRect.toShortString(), null);
    188         try {
    189             if (clipRect.width() > 0 && clipRect.height() > 0) {
    190                 mSurfaceControl.setWindowCrop(clipRect);
    191                 mHiddenForCrop = false;
    192                 updateVisibility();
    193             } else {
    194                 mHiddenForCrop = true;
    195                 mAnimator.destroyPreservedSurfaceLocked();
    196                 updateVisibility();
    197             }
    198         } catch (RuntimeException e) {
    199             Slog.w(TAG, "Error setting crop surface of " + this
    200                     + " crop=" + clipRect.toShortString(), e);
    201             if (!recoveringMemory) {
    202                 mAnimator.reclaimSomeSurfaceMemory("crop", true);
    203             }
    204         }
    205     }
    206 
    207     void clearCropInTransaction(boolean recoveringMemory) {
    208         if (SHOW_TRANSACTIONS) logSurface(
    209                 "CLEAR CROP", null);
    210         try {
    211             Rect clipRect = new Rect(0, 0, -1, -1);
    212             mSurfaceControl.setWindowCrop(clipRect);
    213         } catch (RuntimeException e) {
    214             Slog.w(TAG, "Error setting clearing crop of " + this, e);
    215             if (!recoveringMemory) {
    216                 mAnimator.reclaimSomeSurfaceMemory("crop", true);
    217             }
    218         }
    219     }
    220 
    221     void setFinalCropInTransaction(Rect clipRect) {
    222         if (SHOW_TRANSACTIONS) logSurface(
    223                 "FINAL CROP " + clipRect.toShortString(), null);
    224         try {
    225             mSurfaceControl.setFinalCrop(clipRect);
    226         } catch (RuntimeException e) {
    227             Slog.w(TAG, "Error disconnecting surface in: " + this, e);
    228         }
    229     }
    230 
    231     void setLayer(int layer) {
    232         if (mSurfaceControl != null) {
    233             SurfaceControl.openTransaction();
    234             try {
    235                 mSurfaceControl.setLayer(layer);
    236             } finally {
    237                 SurfaceControl.closeTransaction();
    238             }
    239         }
    240     }
    241 
    242     void setPositionInTransaction(float left, float top, boolean recoveringMemory) {
    243         final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top;
    244         if (surfaceMoved) {
    245             mSurfaceX = left;
    246             mSurfaceY = top;
    247 
    248             try {
    249                 if (SHOW_TRANSACTIONS) logSurface(
    250                         "POS (setPositionInTransaction) @ (" + left + "," + top + ")", null);
    251 
    252                 mSurfaceControl.setPosition(left, top);
    253             } catch (RuntimeException e) {
    254                 Slog.w(TAG, "Error positioning surface of " + this
    255                         + " pos=(" + left + "," + top + ")", e);
    256                 if (!recoveringMemory) {
    257                     mAnimator.reclaimSomeSurfaceMemory("position", true);
    258                 }
    259             }
    260         }
    261     }
    262 
    263     void setGeometryAppliesWithResizeInTransaction(boolean recoveringMemory) {
    264         mSurfaceControl.setGeometryAppliesWithResize();
    265     }
    266 
    267     void setMatrixInTransaction(float dsdx, float dtdx, float dsdy, float dtdy,
    268             boolean recoveringMemory) {
    269         try {
    270             if (SHOW_TRANSACTIONS) logSurface(
    271                     "MATRIX [" + dsdx + "," + dtdx + "," + dsdy + "," + dtdy + "]", null);
    272             mSurfaceControl.setMatrix(
    273                     dsdx, dtdx, dsdy, dtdy);
    274         } catch (RuntimeException e) {
    275             // If something goes wrong with the surface (such
    276             // as running out of memory), don't take down the
    277             // entire system.
    278             Slog.e(TAG, "Error setting matrix on surface surface" + title
    279                     + " MATRIX [" + dsdx + "," + dtdx + "," + dsdy + "," + dtdy + "]", null);
    280             if (!recoveringMemory) {
    281                 mAnimator.reclaimSomeSurfaceMemory("matrix", true);
    282             }
    283         }
    284         return;
    285     }
    286 
    287     boolean setSizeInTransaction(int width, int height, boolean recoveringMemory) {
    288         final boolean surfaceResized = mSurfaceW != width || mSurfaceH != height;
    289         if (surfaceResized) {
    290             mSurfaceW = width;
    291             mSurfaceH = height;
    292 
    293             try {
    294                 if (SHOW_TRANSACTIONS) logSurface(
    295                         "SIZE " + width + "x" + height, null);
    296                 mSurfaceControl.setSize(width, height);
    297             } catch (RuntimeException e) {
    298                 // If something goes wrong with the surface (such
    299                 // as running out of memory), don't take down the
    300                 // entire system.
    301                 Slog.e(TAG, "Error resizing surface of " + title
    302                         + " size=(" + width + "x" + height + ")", e);
    303                 if (!recoveringMemory) {
    304                     mAnimator.reclaimSomeSurfaceMemory("size", true);
    305                 }
    306                 return false;
    307             }
    308             return true;
    309         }
    310         return false;
    311     }
    312 
    313     boolean prepareToShowInTransaction(float alpha, int layer, float dsdx, float dtdx, float dsdy,
    314             float dtdy, boolean recoveringMemory) {
    315         if (mSurfaceControl != null) {
    316             try {
    317                 mSurfaceAlpha = alpha;
    318                 mSurfaceControl.setAlpha(alpha);
    319                 mSurfaceLayer = layer;
    320                 mSurfaceControl.setLayer(layer);
    321                 mSurfaceControl.setMatrix(
    322                         dsdx, dtdx, dsdy, dtdy);
    323 
    324             } catch (RuntimeException e) {
    325                 Slog.w(TAG, "Error updating surface in " + title, e);
    326                 if (!recoveringMemory) {
    327                     mAnimator.reclaimSomeSurfaceMemory("update", true);
    328                 }
    329                 return false;
    330             }
    331         }
    332         return true;
    333     }
    334 
    335     void setTransparentRegionHint(final Region region) {
    336         if (mSurfaceControl == null) {
    337             Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true");
    338             return;
    339         }
    340         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setTransparentRegion");
    341         SurfaceControl.openTransaction();
    342         try {
    343             mSurfaceControl.setTransparentRegionHint(region);
    344         } finally {
    345             SurfaceControl.closeTransaction();
    346             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
    347                     "<<< CLOSE TRANSACTION setTransparentRegion");
    348         }
    349     }
    350 
    351     void setOpaque(boolean isOpaque) {
    352         if (SHOW_TRANSACTIONS) logSurface("isOpaque=" + isOpaque,
    353                 null);
    354 
    355         if (mSurfaceControl == null) {
    356             return;
    357         }
    358         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaqueLocked");
    359         SurfaceControl.openTransaction();
    360         try {
    361             mSurfaceControl.setOpaque(isOpaque);
    362         } finally {
    363             SurfaceControl.closeTransaction();
    364             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaqueLocked");
    365         }
    366     }
    367 
    368     void setSecure(boolean isSecure) {
    369         if (SHOW_TRANSACTIONS) logSurface("isSecure=" + isSecure,
    370                 null);
    371 
    372         if (mSurfaceControl == null) {
    373             return;
    374         }
    375         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setSecureLocked");
    376         SurfaceControl.openTransaction();
    377         try {
    378             mSurfaceControl.setSecure(isSecure);
    379         } finally {
    380             SurfaceControl.closeTransaction();
    381             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setSecureLocked");
    382         }
    383     }
    384 
    385     boolean showRobustlyInTransaction() {
    386         if (SHOW_TRANSACTIONS) logSurface(
    387                 "SHOW (performLayout)", null);
    388         if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
    389                 + " during relayout");
    390         mHiddenForOtherReasons = false;
    391         return updateVisibility();
    392     }
    393 
    394     private boolean updateVisibility() {
    395         if (mHiddenForCrop || mHiddenForOtherReasons) {
    396             if (mSurfaceShown) {
    397                 hideSurface();
    398             }
    399             return false;
    400         } else {
    401             if (!mSurfaceShown) {
    402                 return showSurface();
    403             } else {
    404                 return true;
    405             }
    406         }
    407     }
    408 
    409     private boolean showSurface() {
    410         try {
    411             mSurfaceShown = true;
    412             mSurfaceControl.show();
    413             return true;
    414         } catch (RuntimeException e) {
    415             Slog.w(TAG, "Failure showing surface " + mSurfaceControl + " in " + this, e);
    416         }
    417 
    418         mAnimator.reclaimSomeSurfaceMemory("show", true);
    419 
    420         return false;
    421     }
    422 
    423     void deferTransactionUntil(IBinder handle, long frame) {
    424         // TODO: Logging
    425         mSurfaceControl.deferTransactionUntil(handle, frame);
    426     }
    427 
    428     void forceScaleableInTransaction(boolean force) {
    429         // -1 means we don't override the default or client specified
    430         // scaling mode.
    431         int scalingMode = force ? SCALING_MODE_SCALE_TO_WINDOW : -1;
    432         mSurfaceControl.setOverrideScalingMode(scalingMode);
    433     }
    434 
    435     boolean clearWindowContentFrameStats() {
    436         if (mSurfaceControl == null) {
    437             return false;
    438         }
    439         return mSurfaceControl.clearContentFrameStats();
    440     }
    441 
    442     boolean getWindowContentFrameStats(WindowContentFrameStats outStats) {
    443         if (mSurfaceControl == null) {
    444             return false;
    445         }
    446         return mSurfaceControl.getContentFrameStats(outStats);
    447     }
    448 
    449 
    450     boolean hasSurface() {
    451         return mSurfaceControl != null;
    452     }
    453 
    454     IBinder getHandle() {
    455         if (mSurfaceControl == null) {
    456             return null;
    457         }
    458         return mSurfaceControl.getHandle();
    459     }
    460 
    461     boolean getTransformToDisplayInverse() {
    462         return mSurfaceControl.getTransformToDisplayInverse();
    463     }
    464 
    465     void getSurface(Surface outSurface) {
    466         outSurface.copyFrom(mSurfaceControl);
    467     }
    468 
    469     int getLayer() {
    470         return mSurfaceLayer;
    471     }
    472 
    473     boolean getShown() {
    474         return mSurfaceShown;
    475     }
    476 
    477     void setShown(boolean surfaceShown) {
    478         mSurfaceShown = surfaceShown;
    479     }
    480 
    481     float getX() {
    482         return mSurfaceX;
    483     }
    484 
    485     float getY() {
    486         return mSurfaceY;
    487     }
    488 
    489     float getWidth() {
    490         return mSurfaceW;
    491     }
    492 
    493     float getHeight() {
    494         return mSurfaceH;
    495     }
    496 
    497 
    498     public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
    499         if (dumpAll) {
    500             pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl);
    501         }
    502         pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
    503         pw.print(" layer="); pw.print(mSurfaceLayer);
    504         pw.print(" alpha="); pw.print(mSurfaceAlpha);
    505         pw.print(" rect=("); pw.print(mSurfaceX);
    506         pw.print(","); pw.print(mSurfaceY);
    507         pw.print(") "); pw.print(mSurfaceW);
    508         pw.print(" x "); pw.println(mSurfaceH);
    509     }
    510 
    511     @Override
    512     public String toString() {
    513         return mSurfaceControl.toString();
    514     }
    515 
    516     static class SurfaceTrace extends SurfaceControl {
    517         private final static String SURFACE_TAG = TAG_WITH_CLASS_NAME ? "SurfaceTrace" : TAG_WM;
    518         private final static boolean LOG_SURFACE_TRACE = DEBUG_SURFACE_TRACE;
    519         final static ArrayList<SurfaceTrace> sSurfaces = new ArrayList<SurfaceTrace>();
    520 
    521         private float mSurfaceTraceAlpha = 0;
    522         private int mLayer;
    523         private final PointF mPosition = new PointF();
    524         private final Point mSize = new Point();
    525         private final Rect mWindowCrop = new Rect();
    526         private final Rect mFinalCrop = new Rect();
    527         private boolean mShown = false;
    528         private int mLayerStack;
    529         private boolean mIsOpaque;
    530         private float mDsdx, mDtdx, mDsdy, mDtdy;
    531         private final String mName;
    532 
    533         public SurfaceTrace(SurfaceSession s,
    534                        String name, int w, int h, int format, int flags)
    535                    throws OutOfResourcesException {
    536             super(s, name, w, h, format, flags);
    537             mName = name != null ? name : "Not named";
    538             mSize.set(w, h);
    539             if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
    540                     + Debug.getCallers(3));
    541             synchronized (sSurfaces) {
    542                 sSurfaces.add(0, this);
    543             }
    544         }
    545 
    546         @Override
    547         public void setAlpha(float alpha) {
    548             if (mSurfaceTraceAlpha != alpha) {
    549                 if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setAlpha(" + alpha + "): OLD:" + this +
    550                         ". Called by " + Debug.getCallers(3));
    551                 mSurfaceTraceAlpha = alpha;
    552             }
    553             super.setAlpha(alpha);
    554         }
    555 
    556         @Override
    557         public void setLayer(int zorder) {
    558             if (zorder != mLayer) {
    559                 if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setLayer(" + zorder + "): OLD:" + this
    560                         + ". Called by " + Debug.getCallers(3));
    561                 mLayer = zorder;
    562             }
    563             super.setLayer(zorder);
    564 
    565             synchronized (sSurfaces) {
    566                 sSurfaces.remove(this);
    567                 int i;
    568                 for (i = sSurfaces.size() - 1; i >= 0; i--) {
    569                     SurfaceTrace s = sSurfaces.get(i);
    570                     if (s.mLayer < zorder) {
    571                         break;
    572                     }
    573                 }
    574                 sSurfaces.add(i + 1, this);
    575             }
    576         }
    577 
    578         @Override
    579         public void setPosition(float x, float y) {
    580             if (x != mPosition.x || y != mPosition.y) {
    581                 if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setPosition(" + x + "," + y + "): OLD:"
    582                         + this + ". Called by " + Debug.getCallers(3));
    583                 mPosition.set(x, y);
    584             }
    585             super.setPosition(x, y);
    586         }
    587 
    588         @Override
    589         public void setGeometryAppliesWithResize() {
    590             if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setGeometryAppliesWithResize(): OLD: "
    591                     + this + ". Called by" + Debug.getCallers(3));
    592             super.setGeometryAppliesWithResize();
    593         }
    594 
    595         @Override
    596         public void setSize(int w, int h) {
    597             if (w != mSize.x || h != mSize.y) {
    598                 if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setSize(" + w + "," + h + "): OLD:"
    599                         + this + ". Called by " + Debug.getCallers(3));
    600                 mSize.set(w, h);
    601             }
    602             super.setSize(w, h);
    603         }
    604 
    605         @Override
    606         public void setWindowCrop(Rect crop) {
    607             if (crop != null) {
    608                 if (!crop.equals(mWindowCrop)) {
    609                     if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setWindowCrop("
    610                             + crop.toShortString() + "): OLD:" + this + ". Called by "
    611                             + Debug.getCallers(3));
    612                     mWindowCrop.set(crop);
    613                 }
    614             }
    615             super.setWindowCrop(crop);
    616         }
    617 
    618         @Override
    619         public void setFinalCrop(Rect crop) {
    620             if (crop != null) {
    621                 if (!crop.equals(mFinalCrop)) {
    622                     if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setFinalCrop("
    623                             + crop.toShortString() + "): OLD:" + this + ". Called by "
    624                             + Debug.getCallers(3));
    625                     mFinalCrop.set(crop);
    626                 }
    627             }
    628             super.setFinalCrop(crop);
    629         }
    630 
    631         @Override
    632         public void setLayerStack(int layerStack) {
    633             if (layerStack != mLayerStack) {
    634                 if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setLayerStack(" + layerStack + "): OLD:"
    635                         + this + ". Called by " + Debug.getCallers(3));
    636                 mLayerStack = layerStack;
    637             }
    638             super.setLayerStack(layerStack);
    639         }
    640 
    641         @Override
    642         public void setOpaque(boolean isOpaque) {
    643             if (isOpaque != mIsOpaque) {
    644                 if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setOpaque(" + isOpaque + "): OLD:"
    645                         + this + ". Called by " + Debug.getCallers(3));
    646                 mIsOpaque = isOpaque;
    647             }
    648             super.setOpaque(isOpaque);
    649         }
    650 
    651         @Override
    652         public void setSecure(boolean isSecure) {
    653             super.setSecure(isSecure);
    654         }
    655 
    656         @Override
    657         public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
    658             if (dsdx != mDsdx || dtdx != mDtdx || dsdy != mDsdy || dtdy != mDtdy) {
    659                 if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setMatrix(" + dsdx + "," + dtdx + ","
    660                         + dsdy + "," + dtdy + "): OLD:" + this + ". Called by "
    661                         + Debug.getCallers(3));
    662                 mDsdx = dsdx;
    663                 mDtdx = dtdx;
    664                 mDsdy = dsdy;
    665                 mDtdy = dtdy;
    666             }
    667             super.setMatrix(dsdx, dtdx, dsdy, dtdy);
    668         }
    669 
    670         @Override
    671         public void hide() {
    672             if (mShown) {
    673                 if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "hide: OLD:" + this + ". Called by "
    674                         + Debug.getCallers(3));
    675                 mShown = false;
    676             }
    677             super.hide();
    678         }
    679 
    680         @Override
    681         public void show() {
    682             if (!mShown) {
    683                 if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "show: OLD:" + this + ". Called by "
    684                         + Debug.getCallers(3));
    685                 mShown = true;
    686             }
    687             super.show();
    688         }
    689 
    690         @Override
    691         public void destroy() {
    692             super.destroy();
    693             if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "destroy: " + this + ". Called by "
    694                     + Debug.getCallers(3));
    695             synchronized (sSurfaces) {
    696                 sSurfaces.remove(this);
    697             }
    698         }
    699 
    700         @Override
    701         public void release() {
    702             super.release();
    703             if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "release: " + this + ". Called by "
    704                     + Debug.getCallers(3));
    705             synchronized (sSurfaces) {
    706                 sSurfaces.remove(this);
    707             }
    708         }
    709 
    710         @Override
    711         public void setTransparentRegionHint(Region region) {
    712             if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setTransparentRegionHint(" + region
    713                     + "): OLD: " + this + " . Called by " + Debug.getCallers(3));
    714             super.setTransparentRegionHint(region);
    715         }
    716 
    717         static void dumpAllSurfaces(PrintWriter pw, String header) {
    718             synchronized (sSurfaces) {
    719                 final int N = sSurfaces.size();
    720                 if (N <= 0) {
    721                     return;
    722                 }
    723                 if (header != null) {
    724                     pw.println(header);
    725                 }
    726                 pw.println("WINDOW MANAGER SURFACES (dumpsys window surfaces)");
    727                 for (int i = 0; i < N; i++) {
    728                     SurfaceTrace s = sSurfaces.get(i);
    729                     pw.print("  Surface #"); pw.print(i); pw.print(": #");
    730                             pw.print(Integer.toHexString(System.identityHashCode(s)));
    731                             pw.print(" "); pw.println(s.mName);
    732                     pw.print("    mLayerStack="); pw.print(s.mLayerStack);
    733                             pw.print(" mLayer="); pw.println(s.mLayer);
    734                     pw.print("    mShown="); pw.print(s.mShown); pw.print(" mAlpha=");
    735                             pw.print(s.mSurfaceTraceAlpha); pw.print(" mIsOpaque=");
    736                             pw.println(s.mIsOpaque);
    737                     pw.print("    mPosition="); pw.print(s.mPosition.x); pw.print(",");
    738                             pw.print(s.mPosition.y);
    739                             pw.print(" mSize="); pw.print(s.mSize.x); pw.print("x");
    740                             pw.println(s.mSize.y);
    741                     pw.print("    mCrop="); s.mWindowCrop.printShortString(pw); pw.println();
    742                     pw.print("    mFinalCrop="); s.mFinalCrop.printShortString(pw); pw.println();
    743                     pw.print("    Transform: ("); pw.print(s.mDsdx); pw.print(", ");
    744                             pw.print(s.mDtdx); pw.print(", "); pw.print(s.mDsdy);
    745                             pw.print(", "); pw.print(s.mDtdy); pw.println(")");
    746                 }
    747             }
    748         }
    749 
    750         @Override
    751         public String toString() {
    752             return "Surface " + Integer.toHexString(System.identityHashCode(this)) + " "
    753                     + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer
    754                     + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y
    755                     + " " + mSize.x + "x" + mSize.y
    756                     + " crop=" + mWindowCrop.toShortString()
    757                     + " opaque=" + mIsOpaque
    758                     + " (" + mDsdx + "," + mDtdx + "," + mDsdy + "," + mDtdy + ")";
    759         }
    760     }
    761 
    762     class SurfaceControlWithBackground extends SurfaceControl {
    763         private SurfaceControl mBackgroundControl;
    764         private boolean mOpaque = true;
    765         private boolean mAppForcedInvisible = false;
    766         private AppWindowToken mAppToken;
    767         public boolean mVisible = false;
    768         public int mLayer = -1;
    769 
    770         public SurfaceControlWithBackground(SurfaceSession s,
    771                         String name, int w, int h, int format, int flags,
    772                         AppWindowToken token)
    773                    throws OutOfResourcesException {
    774             super(s, name, w, h, format, flags);
    775             mBackgroundControl = new SurfaceControl(s, name, w, h,
    776                     PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM);
    777             mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
    778             mAppToken = token;
    779 
    780             mAppToken.addSurfaceViewBackground(this);
    781         }
    782 
    783         @Override
    784         public void setAlpha(float alpha) {
    785             super.setAlpha(alpha);
    786             mBackgroundControl.setAlpha(alpha);
    787         }
    788 
    789         @Override
    790         public void setLayer(int zorder) {
    791             super.setLayer(zorder);
    792             mBackgroundControl.setLayer(zorder - 1);
    793             if (mLayer != zorder) {
    794                 mLayer = zorder;
    795                 mAppToken.updateSurfaceViewBackgroundVisibilities();
    796             }
    797         }
    798 
    799         @Override
    800         public void setPosition(float x, float y) {
    801             super.setPosition(x, y);
    802             mBackgroundControl.setPosition(x, y);
    803         }
    804 
    805         @Override
    806         public void setSize(int w, int h) {
    807             super.setSize(w, h);
    808             mBackgroundControl.setSize(w, h);
    809         }
    810 
    811         @Override
    812         public void setWindowCrop(Rect crop) {
    813             super.setWindowCrop(crop);
    814             mBackgroundControl.setWindowCrop(crop);
    815         }
    816 
    817         @Override
    818         public void setFinalCrop(Rect crop) {
    819             super.setFinalCrop(crop);
    820             mBackgroundControl.setFinalCrop(crop);
    821         }
    822 
    823         @Override
    824         public void setLayerStack(int layerStack) {
    825             super.setLayerStack(layerStack);
    826             mBackgroundControl.setLayerStack(layerStack);
    827         }
    828 
    829         @Override
    830         public void setOpaque(boolean isOpaque) {
    831             super.setOpaque(isOpaque);
    832             mOpaque = isOpaque;
    833             updateBackgroundVisibility(mAppForcedInvisible);
    834         }
    835 
    836         @Override
    837         public void setSecure(boolean isSecure) {
    838             super.setSecure(isSecure);
    839         }
    840 
    841         @Override
    842         public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
    843             super.setMatrix(dsdx, dtdx, dsdy, dtdy);
    844             mBackgroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy);
    845         }
    846 
    847         @Override
    848         public void hide() {
    849             super.hide();
    850             if (mVisible) {
    851                 mVisible = false;
    852                 mAppToken.updateSurfaceViewBackgroundVisibilities();
    853             }
    854         }
    855 
    856         @Override
    857         public void show() {
    858             super.show();
    859             if (!mVisible) {
    860                 mVisible = true;
    861                 mAppToken.updateSurfaceViewBackgroundVisibilities();
    862             }
    863         }
    864 
    865         @Override
    866         public void destroy() {
    867             super.destroy();
    868             mBackgroundControl.destroy();
    869             mAppToken.removeSurfaceViewBackground(this);
    870          }
    871 
    872         @Override
    873         public void release() {
    874             super.release();
    875             mBackgroundControl.release();
    876         }
    877 
    878         @Override
    879         public void setTransparentRegionHint(Region region) {
    880             super.setTransparentRegionHint(region);
    881             mBackgroundControl.setTransparentRegionHint(region);
    882         }
    883 
    884         @Override
    885         public void deferTransactionUntil(IBinder handle, long frame) {
    886             super.deferTransactionUntil(handle, frame);
    887             mBackgroundControl.deferTransactionUntil(handle, frame);
    888         }
    889 
    890         void updateBackgroundVisibility(boolean forcedInvisible) {
    891             mAppForcedInvisible = forcedInvisible;
    892             if (mOpaque && mVisible && !mAppForcedInvisible) {
    893                 mBackgroundControl.show();
    894             } else {
    895                 mBackgroundControl.hide();
    896             }
    897         }
    898     }
    899 }
    900