blob: fd72a4af98483db26bbc51d6aef3be12621ef431 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wm;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.util.Slog;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import java.io.PrintWriter;
/**
* Four black surfaces put together to make a black frame.
*/
public class BlackFrame {
class BlackSurface {
final int left;
final int top;
final int layer;
final SurfaceControl surface;
BlackSurface(SurfaceControl.Transaction transaction, int layer,
int l, int t, int r, int b, DisplayContent dc) throws OutOfResourcesException {
left = l;
top = t;
this.layer = layer;
int w = r-l;
int h = b-t;
surface = dc.makeOverlay()
.setName("BlackSurface")
.setColorLayer()
.setParent(null) // TODO: Work-around for b/69259549
.build();
transaction.setWindowCrop(surface, w, h);
transaction.setLayerStack(surface, dc.getDisplayId());
transaction.setAlpha(surface, 1);
transaction.setLayer(surface, layer);
transaction.setPosition(surface, left, top);
transaction.show(surface);
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM,
" BLACK " + surface + ": CREATE layer=" + layer);
}
void setAlpha(SurfaceControl.Transaction t, float alpha) {
t.setAlpha(surface, alpha);
}
void setMatrix(SurfaceControl.Transaction t, Matrix matrix) {
mTmpMatrix.setTranslate(left, top);
mTmpMatrix.postConcat(matrix);
mTmpMatrix.getValues(mTmpFloats);
t.setPosition(surface, mTmpFloats[Matrix.MTRANS_X],
mTmpFloats[Matrix.MTRANS_Y]);
t.setMatrix(surface,
mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
if (false) {
Slog.i(TAG_WM, "Black Surface @ (" + left + "," + top + "): ("
+ mTmpFloats[Matrix.MTRANS_X] + ","
+ mTmpFloats[Matrix.MTRANS_Y] + ") matrix=["
+ mTmpFloats[Matrix.MSCALE_X] + ","
+ mTmpFloats[Matrix.MSCALE_Y] + "]["
+ mTmpFloats[Matrix.MSKEW_X] + ","
+ mTmpFloats[Matrix.MSKEW_Y] + "]");
}
}
void clearMatrix(SurfaceControl.Transaction t) {
t.setMatrix(surface, 1, 0, 0, 1);
}
}
final Rect mOuterRect;
final Rect mInnerRect;
final Matrix mTmpMatrix = new Matrix();
final float[] mTmpFloats = new float[9];
final BlackSurface[] mBlackSurfaces = new BlackSurface[4];
final boolean mForceDefaultOrientation;
public void printTo(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("Outer: "); mOuterRect.printShortString(pw);
pw.print(" / Inner: "); mInnerRect.printShortString(pw);
pw.println();
for (int i=0; i<mBlackSurfaces.length; i++) {
BlackSurface bs = mBlackSurfaces[i];
pw.print(prefix); pw.print("#"); pw.print(i);
pw.print(": "); pw.print(bs.surface);
pw.print(" left="); pw.print(bs.left);
pw.print(" top="); pw.println(bs.top);
}
}
public BlackFrame(SurfaceControl.Transaction t,
Rect outer, Rect inner, int layer, DisplayContent dc,
boolean forceDefaultOrientation) throws OutOfResourcesException {
boolean success = false;
mForceDefaultOrientation = forceDefaultOrientation;
// TODO: Why do we use 4 surfaces instead of just one big one behind the screenshot?
// b/68253229
mOuterRect = new Rect(outer);
mInnerRect = new Rect(inner);
try {
if (outer.top < inner.top) {
mBlackSurfaces[0] = new BlackSurface(t, layer,
outer.left, outer.top, inner.right, inner.top, dc);
}
if (outer.left < inner.left) {
mBlackSurfaces[1] = new BlackSurface(t, layer,
outer.left, inner.top, inner.left, outer.bottom, dc);
}
if (outer.bottom > inner.bottom) {
mBlackSurfaces[2] = new BlackSurface(t, layer,
inner.left, inner.bottom, outer.right, outer.bottom, dc);
}
if (outer.right > inner.right) {
mBlackSurfaces[3] = new BlackSurface(t, layer,
inner.right, outer.top, outer.right, inner.bottom, dc);
}
success = true;
} finally {
if (!success) {
kill();
}
}
}
public void kill() {
if (mBlackSurfaces != null) {
for (int i=0; i<mBlackSurfaces.length; i++) {
if (mBlackSurfaces[i] != null) {
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM,
" BLACK " + mBlackSurfaces[i].surface + ": DESTROY");
mBlackSurfaces[i].surface.destroy();
mBlackSurfaces[i] = null;
}
}
}
}
public void hide(SurfaceControl.Transaction t) {
if (mBlackSurfaces != null) {
for (int i=0; i<mBlackSurfaces.length; i++) {
if (mBlackSurfaces[i] != null) {
t.hide(mBlackSurfaces[i].surface);
}
}
}
}
public void setAlpha(SurfaceControl.Transaction t, float alpha) {
for (int i=0; i<mBlackSurfaces.length; i++) {
if (mBlackSurfaces[i] != null) {
mBlackSurfaces[i].setAlpha(t, alpha);
}
}
}
public void setMatrix(SurfaceControl.Transaction t, Matrix matrix) {
for (int i=0; i<mBlackSurfaces.length; i++) {
if (mBlackSurfaces[i] != null) {
mBlackSurfaces[i].setMatrix(t, matrix);
}
}
}
public void clearMatrix(SurfaceControl.Transaction t) {
for (int i=0; i<mBlackSurfaces.length; i++) {
if (mBlackSurfaces[i] != null) {
mBlackSurfaces[i].clearMatrix(t);
}
}
}
}