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