1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
19import java.io.PrintWriter;
20
21import android.graphics.Matrix;
22import android.graphics.PixelFormat;
23import android.graphics.Rect;
24import android.util.Slog;
25import android.view.Surface;
26import android.view.SurfaceSession;
27
28/**
29 * Four black surfaces put together to make a black frame.
30 */
31public class BlackFrame {
32    class BlackSurface {
33        final int left;
34        final int top;
35        final int layer;
36        final Surface surface;
37
38        BlackSurface(SurfaceSession session, int layer, int l, int t, int r, int b, int layerStack)
39                throws Surface.OutOfResourcesException {
40            left = l;
41            top = t;
42            this.layer = layer;
43            int w = r-l;
44            int h = b-t;
45            if (WindowManagerService.DEBUG_SURFACE_TRACE) {
46                surface = new WindowStateAnimator.SurfaceTrace(session, "BlackSurface("
47                        + l + ", " + t + ")",
48                        w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM | Surface.HIDDEN);
49            } else {
50                surface = new Surface(session, "BlackSurface",
51                        w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM | Surface.HIDDEN);
52            }
53            surface.setAlpha(1);
54            surface.setLayerStack(layerStack);
55            surface.setLayer(layer);
56            surface.show();
57            if (WindowManagerService.SHOW_TRANSACTIONS ||
58                    WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
59                            "  BLACK " + surface + ": CREATE layer=" + layer);
60        }
61
62        void setMatrix(Matrix matrix) {
63            mTmpMatrix.setTranslate(left, top);
64            mTmpMatrix.postConcat(matrix);
65            mTmpMatrix.getValues(mTmpFloats);
66            surface.setPosition(mTmpFloats[Matrix.MTRANS_X],
67                    mTmpFloats[Matrix.MTRANS_Y]);
68            surface.setMatrix(
69                    mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
70                    mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
71            if (false) {
72                Slog.i(WindowManagerService.TAG, "Black Surface @ (" + left + "," + top + "): ("
73                        + mTmpFloats[Matrix.MTRANS_X] + ","
74                        + mTmpFloats[Matrix.MTRANS_Y] + ") matrix=["
75                        + mTmpFloats[Matrix.MSCALE_X] + ","
76                        + mTmpFloats[Matrix.MSCALE_Y] + "]["
77                        + mTmpFloats[Matrix.MSKEW_X] + ","
78                        + mTmpFloats[Matrix.MSKEW_Y] + "]");
79            }
80        }
81
82        void clearMatrix() {
83            surface.setMatrix(1, 0, 0, 1);
84        }
85    }
86
87    final Rect mOuterRect;
88    final Rect mInnerRect;
89    final Matrix mTmpMatrix = new Matrix();
90    final float[] mTmpFloats = new float[9];
91    final BlackSurface[] mBlackSurfaces = new BlackSurface[4];
92
93    public void printTo(String prefix, PrintWriter pw) {
94        pw.print(prefix); pw.print("Outer: "); mOuterRect.printShortString(pw);
95                pw.print(" / Inner: "); mInnerRect.printShortString(pw);
96                pw.println();
97        for (int i=0; i<mBlackSurfaces.length; i++) {
98            BlackSurface bs = mBlackSurfaces[i];
99            pw.print(prefix); pw.print("#"); pw.print(i);
100                    pw.print(": "); pw.print(bs.surface);
101                    pw.print(" left="); pw.print(bs.left);
102                    pw.print(" top="); pw.println(bs.top);
103        }
104    }
105
106    public BlackFrame(SurfaceSession session, Rect outer, Rect inner,
107            int layer, final int layerStack) throws Surface.OutOfResourcesException {
108        boolean success = false;
109
110        mOuterRect = new Rect(outer);
111        mInnerRect = new Rect(inner);
112        try {
113            if (outer.top < inner.top) {
114                mBlackSurfaces[0] = new BlackSurface(session, layer,
115                        outer.left, outer.top, inner.right, inner.top, layerStack);
116            }
117            if (outer.left < inner.left) {
118                mBlackSurfaces[1] = new BlackSurface(session, layer,
119                        outer.left, inner.top, inner.left, outer.bottom, layerStack);
120            }
121            if (outer.bottom > inner.bottom) {
122                mBlackSurfaces[2] = new BlackSurface(session, layer,
123                        inner.left, inner.bottom, outer.right, outer.bottom, layerStack);
124            }
125            if (outer.right > inner.right) {
126                mBlackSurfaces[3] = new BlackSurface(session, layer,
127                        inner.right, outer.top, outer.right, inner.bottom, layerStack);
128            }
129            success = true;
130        } finally {
131            if (!success) {
132                kill();
133            }
134        }
135    }
136
137    public void kill() {
138        if (mBlackSurfaces != null) {
139            for (int i=0; i<mBlackSurfaces.length; i++) {
140                if (mBlackSurfaces[i] != null) {
141                    if (WindowManagerService.SHOW_TRANSACTIONS ||
142                            WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(
143                                    WindowManagerService.TAG,
144                                    "  BLACK " + mBlackSurfaces[i].surface + ": DESTROY");
145                    mBlackSurfaces[i].surface.destroy();
146                    mBlackSurfaces[i] = null;
147                }
148            }
149        }
150    }
151
152    public void hide() {
153        if (mBlackSurfaces != null) {
154            for (int i=0; i<mBlackSurfaces.length; i++) {
155                if (mBlackSurfaces[i] != null) {
156                    mBlackSurfaces[i].surface.hide();
157                }
158            }
159        }
160    }
161
162    public void setMatrix(Matrix matrix) {
163        for (int i=0; i<mBlackSurfaces.length; i++) {
164            if (mBlackSurfaces[i] != null) {
165                mBlackSurfaces[i].setMatrix(matrix);
166            }
167        }
168    }
169
170    public void clearMatrix() {
171        for (int i=0; i<mBlackSurfaces.length; i++) {
172            if (mBlackSurfaces[i] != null) {
173                mBlackSurfaces[i].clearMatrix();
174            }
175        }
176    }
177}
178