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