WindowSurfaceController.java revision 91b22809648a33d64c159e8496773b1b3b2ab6ca
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.PixelFormat;
30import android.graphics.Point;
31import android.graphics.PointF;
32import android.graphics.Rect;
33import android.graphics.Region;
34import android.os.IBinder;
35import android.os.Debug;
36import android.view.Surface;
37import android.view.SurfaceControl;
38import android.view.SurfaceSession;
39import android.view.WindowContentFrameStats;
40import android.view.Surface.OutOfResourcesException;
41
42import android.util.Slog;
43
44import java.io.PrintWriter;
45import java.util.ArrayList;
46
47class 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 setPositionAppliesWithResizeInTransaction(boolean recoveringMemory) {
264        mSurfaceControl.setPositionAppliesWithResize();
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    void getSurface(Surface outSurface) {
462        outSurface.copyFrom(mSurfaceControl);
463    }
464
465    int getLayer() {
466        return mSurfaceLayer;
467    }
468
469    boolean getShown() {
470        return mSurfaceShown;
471    }
472
473    void setShown(boolean surfaceShown) {
474        mSurfaceShown = surfaceShown;
475    }
476
477    float getX() {
478        return mSurfaceX;
479    }
480
481    float getY() {
482        return mSurfaceY;
483    }
484
485    float getWidth() {
486        return mSurfaceW;
487    }
488
489    float getHeight() {
490        return mSurfaceH;
491    }
492
493
494    public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
495        if (dumpAll) {
496            pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl);
497        }
498        pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
499        pw.print(" layer="); pw.print(mSurfaceLayer);
500        pw.print(" alpha="); pw.print(mSurfaceAlpha);
501        pw.print(" rect=("); pw.print(mSurfaceX);
502        pw.print(","); pw.print(mSurfaceY);
503        pw.print(") "); pw.print(mSurfaceW);
504        pw.print(" x "); pw.println(mSurfaceH);
505    }
506
507    @Override
508    public String toString() {
509        return mSurfaceControl.toString();
510    }
511
512    static class SurfaceTrace extends SurfaceControl {
513        private final static String SURFACE_TAG = TAG_WITH_CLASS_NAME ? "SurfaceTrace" : TAG_WM;
514        private final static boolean LOG_SURFACE_TRACE = DEBUG_SURFACE_TRACE;
515        final static ArrayList<SurfaceTrace> sSurfaces = new ArrayList<SurfaceTrace>();
516
517        private float mSurfaceTraceAlpha = 0;
518        private int mLayer;
519        private final PointF mPosition = new PointF();
520        private final Point mSize = new Point();
521        private final Rect mWindowCrop = new Rect();
522        private final Rect mFinalCrop = new Rect();
523        private boolean mShown = false;
524        private int mLayerStack;
525        private boolean mIsOpaque;
526        private float mDsdx, mDtdx, mDsdy, mDtdy;
527        private final String mName;
528
529        public SurfaceTrace(SurfaceSession s,
530                       String name, int w, int h, int format, int flags)
531                   throws OutOfResourcesException {
532            super(s, name, w, h, format, flags);
533            mName = name != null ? name : "Not named";
534            mSize.set(w, h);
535            if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
536                    + Debug.getCallers(3));
537            synchronized (sSurfaces) {
538                sSurfaces.add(0, this);
539            }
540        }
541
542        @Override
543        public void setAlpha(float alpha) {
544            if (mSurfaceTraceAlpha != alpha) {
545                if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setAlpha(" + alpha + "): OLD:" + this +
546                        ". Called by " + Debug.getCallers(3));
547                mSurfaceTraceAlpha = alpha;
548            }
549            super.setAlpha(alpha);
550        }
551
552        @Override
553        public void setLayer(int zorder) {
554            if (zorder != mLayer) {
555                if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setLayer(" + zorder + "): OLD:" + this
556                        + ". Called by " + Debug.getCallers(3));
557                mLayer = zorder;
558            }
559            super.setLayer(zorder);
560
561            synchronized (sSurfaces) {
562                sSurfaces.remove(this);
563                int i;
564                for (i = sSurfaces.size() - 1; i >= 0; i--) {
565                    SurfaceTrace s = sSurfaces.get(i);
566                    if (s.mLayer < zorder) {
567                        break;
568                    }
569                }
570                sSurfaces.add(i + 1, this);
571            }
572        }
573
574        @Override
575        public void setPosition(float x, float y) {
576            if (x != mPosition.x || y != mPosition.y) {
577                if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setPosition(" + x + "," + y + "): OLD:"
578                        + this + ". Called by " + Debug.getCallers(3));
579                mPosition.set(x, y);
580            }
581            super.setPosition(x, y);
582        }
583
584        @Override
585        public void setPositionAppliesWithResize() {
586            if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setPositionAppliesWithResize(): OLD: "
587                    + this + ". Called by" + Debug.getCallers(9));
588            super.setPositionAppliesWithResize();
589        }
590
591        @Override
592        public void setSize(int w, int h) {
593            if (w != mSize.x || h != mSize.y) {
594                if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setSize(" + w + "," + h + "): OLD:"
595                        + this + ". Called by " + Debug.getCallers(3));
596                mSize.set(w, h);
597            }
598            super.setSize(w, h);
599        }
600
601        @Override
602        public void setWindowCrop(Rect crop) {
603            if (crop != null) {
604                if (!crop.equals(mWindowCrop)) {
605                    if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setWindowCrop("
606                            + crop.toShortString() + "): OLD:" + this + ". Called by "
607                            + Debug.getCallers(3));
608                    mWindowCrop.set(crop);
609                }
610            }
611            super.setWindowCrop(crop);
612        }
613
614        @Override
615        public void setFinalCrop(Rect crop) {
616            if (crop != null) {
617                if (!crop.equals(mFinalCrop)) {
618                    if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setFinalCrop("
619                            + crop.toShortString() + "): OLD:" + this + ". Called by "
620                            + Debug.getCallers(3));
621                    mFinalCrop.set(crop);
622                }
623            }
624            super.setFinalCrop(crop);
625        }
626
627        @Override
628        public void setLayerStack(int layerStack) {
629            if (layerStack != mLayerStack) {
630                if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setLayerStack(" + layerStack + "): OLD:"
631                        + this + ". Called by " + Debug.getCallers(3));
632                mLayerStack = layerStack;
633            }
634            super.setLayerStack(layerStack);
635        }
636
637        @Override
638        public void setOpaque(boolean isOpaque) {
639            if (isOpaque != mIsOpaque) {
640                if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setOpaque(" + isOpaque + "): OLD:"
641                        + this + ". Called by " + Debug.getCallers(3));
642                mIsOpaque = isOpaque;
643            }
644            super.setOpaque(isOpaque);
645        }
646
647        @Override
648        public void setSecure(boolean isSecure) {
649            super.setSecure(isSecure);
650        }
651
652        @Override
653        public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
654            if (dsdx != mDsdx || dtdx != mDtdx || dsdy != mDsdy || dtdy != mDtdy) {
655                if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setMatrix(" + dsdx + "," + dtdx + ","
656                        + dsdy + "," + dtdy + "): OLD:" + this + ". Called by "
657                        + Debug.getCallers(3));
658                mDsdx = dsdx;
659                mDtdx = dtdx;
660                mDsdy = dsdy;
661                mDtdy = dtdy;
662            }
663            super.setMatrix(dsdx, dtdx, dsdy, dtdy);
664        }
665
666        @Override
667        public void hide() {
668            if (mShown) {
669                if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "hide: OLD:" + this + ". Called by "
670                        + Debug.getCallers(3));
671                mShown = false;
672            }
673            super.hide();
674        }
675
676        @Override
677        public void show() {
678            if (!mShown) {
679                if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "show: OLD:" + this + ". Called by "
680                        + Debug.getCallers(3));
681                mShown = true;
682            }
683            super.show();
684        }
685
686        @Override
687        public void destroy() {
688            super.destroy();
689            if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "destroy: " + this + ". Called by "
690                    + Debug.getCallers(3));
691            synchronized (sSurfaces) {
692                sSurfaces.remove(this);
693            }
694        }
695
696        @Override
697        public void release() {
698            super.release();
699            if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "release: " + this + ". Called by "
700                    + Debug.getCallers(3));
701            synchronized (sSurfaces) {
702                sSurfaces.remove(this);
703            }
704        }
705
706        @Override
707        public void setTransparentRegionHint(Region region) {
708            if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setTransparentRegionHint(" + region
709                    + "): OLD: " + this + " . Called by " + Debug.getCallers(3));
710            super.setTransparentRegionHint(region);
711        }
712
713        static void dumpAllSurfaces(PrintWriter pw, String header) {
714            synchronized (sSurfaces) {
715                final int N = sSurfaces.size();
716                if (N <= 0) {
717                    return;
718                }
719                if (header != null) {
720                    pw.println(header);
721                }
722                pw.println("WINDOW MANAGER SURFACES (dumpsys window surfaces)");
723                for (int i = 0; i < N; i++) {
724                    SurfaceTrace s = sSurfaces.get(i);
725                    pw.print("  Surface #"); pw.print(i); pw.print(": #");
726                            pw.print(Integer.toHexString(System.identityHashCode(s)));
727                            pw.print(" "); pw.println(s.mName);
728                    pw.print("    mLayerStack="); pw.print(s.mLayerStack);
729                            pw.print(" mLayer="); pw.println(s.mLayer);
730                    pw.print("    mShown="); pw.print(s.mShown); pw.print(" mAlpha=");
731                            pw.print(s.mSurfaceTraceAlpha); pw.print(" mIsOpaque=");
732                            pw.println(s.mIsOpaque);
733                    pw.print("    mPosition="); pw.print(s.mPosition.x); pw.print(",");
734                            pw.print(s.mPosition.y);
735                            pw.print(" mSize="); pw.print(s.mSize.x); pw.print("x");
736                            pw.println(s.mSize.y);
737                    pw.print("    mCrop="); s.mWindowCrop.printShortString(pw); pw.println();
738                    pw.print("    mFinalCrop="); s.mFinalCrop.printShortString(pw); pw.println();
739                    pw.print("    Transform: ("); pw.print(s.mDsdx); pw.print(", ");
740                            pw.print(s.mDtdx); pw.print(", "); pw.print(s.mDsdy);
741                            pw.print(", "); pw.print(s.mDtdy); pw.println(")");
742                }
743            }
744        }
745
746        @Override
747        public String toString() {
748            return "Surface " + Integer.toHexString(System.identityHashCode(this)) + " "
749                    + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer
750                    + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y
751                    + " " + mSize.x + "x" + mSize.y
752                    + " crop=" + mWindowCrop.toShortString()
753                    + " opaque=" + mIsOpaque
754                    + " (" + mDsdx + "," + mDtdx + "," + mDsdy + "," + mDtdy + ")";
755        }
756    }
757
758    class SurfaceControlWithBackground extends SurfaceControl {
759        private SurfaceControl mBackgroundControl;
760        private boolean mOpaque = true;
761        private boolean mAppForcedInvisible = false;
762        private AppWindowToken mAppToken;
763        public boolean mVisible = false;
764        public int mLayer = -1;
765
766        public SurfaceControlWithBackground(SurfaceSession s,
767                        String name, int w, int h, int format, int flags,
768                        AppWindowToken token)
769                   throws OutOfResourcesException {
770            super(s, name, w, h, format, flags);
771            mBackgroundControl = new SurfaceControl(s, name, w, h,
772                    PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM);
773            mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
774            mAppToken = token;
775
776            mAppToken.addSurfaceViewBackground(this);
777        }
778
779        @Override
780        public void setAlpha(float alpha) {
781            super.setAlpha(alpha);
782            mBackgroundControl.setAlpha(alpha);
783        }
784
785        @Override
786        public void setLayer(int zorder) {
787            super.setLayer(zorder);
788            mBackgroundControl.setLayer(zorder - 1);
789            if (mLayer != zorder) {
790                mLayer = zorder;
791                mAppToken.updateSurfaceViewBackgroundVisibilities();
792            }
793        }
794
795        @Override
796        public void setPosition(float x, float y) {
797            super.setPosition(x, y);
798            mBackgroundControl.setPosition(x, y);
799        }
800
801        @Override
802        public void setSize(int w, int h) {
803            super.setSize(w, h);
804            mBackgroundControl.setSize(w, h);
805        }
806
807        @Override
808        public void setWindowCrop(Rect crop) {
809            super.setWindowCrop(crop);
810            mBackgroundControl.setWindowCrop(crop);
811        }
812
813        @Override
814        public void setFinalCrop(Rect crop) {
815            super.setFinalCrop(crop);
816            mBackgroundControl.setFinalCrop(crop);
817        }
818
819        @Override
820        public void setLayerStack(int layerStack) {
821            super.setLayerStack(layerStack);
822            mBackgroundControl.setLayerStack(layerStack);
823        }
824
825        @Override
826        public void setOpaque(boolean isOpaque) {
827            super.setOpaque(isOpaque);
828            mOpaque = isOpaque;
829            updateBackgroundVisibility(mAppForcedInvisible);
830        }
831
832        @Override
833        public void setSecure(boolean isSecure) {
834            super.setSecure(isSecure);
835        }
836
837        @Override
838        public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
839            super.setMatrix(dsdx, dtdx, dsdy, dtdy);
840            mBackgroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy);
841        }
842
843        @Override
844        public void hide() {
845            super.hide();
846            if (mVisible) {
847                mVisible = false;
848                mAppToken.updateSurfaceViewBackgroundVisibilities();
849            }
850        }
851
852        @Override
853        public void show() {
854            super.show();
855            if (!mVisible) {
856                mVisible = true;
857                mAppToken.updateSurfaceViewBackgroundVisibilities();
858            }
859        }
860
861        @Override
862        public void destroy() {
863            super.destroy();
864            mBackgroundControl.destroy();
865            mAppToken.removeSurfaceViewBackground(this);
866         }
867
868        @Override
869        public void release() {
870            super.release();
871            mBackgroundControl.release();
872        }
873
874        @Override
875        public void setTransparentRegionHint(Region region) {
876            super.setTransparentRegionHint(region);
877            mBackgroundControl.setTransparentRegionHint(region);
878        }
879
880        @Override
881        public void deferTransactionUntil(IBinder handle, long frame) {
882            super.deferTransactionUntil(handle, frame);
883            mBackgroundControl.deferTransactionUntil(handle, frame);
884        }
885
886        void updateBackgroundVisibility(boolean forcedInvisible) {
887            mAppForcedInvisible = forcedInvisible;
888            if (mOpaque && mVisible && !mAppForcedInvisible) {
889                mBackgroundControl.show();
890            } else {
891                mBackgroundControl.hide();
892            }
893        }
894    }
895}
896