1/*
2 * Copyright (C) 2010 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
19
20import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
21import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
22
23import android.graphics.Canvas;
24import android.graphics.Color;
25import android.graphics.PixelFormat;
26import android.graphics.Rect;
27import android.graphics.Region;
28import android.view.Display;
29import android.view.Surface.OutOfResourcesException;
30import android.view.Surface;
31import android.view.SurfaceControl;
32import android.view.SurfaceSession;
33
34class StrictModeFlash {
35    private static final String TAG = TAG_WITH_CLASS_NAME ? "StrictModeFlash" : TAG_WM;
36
37    private final SurfaceControl mSurfaceControl;
38    private final Surface mSurface = new Surface();
39    private int mLastDW;
40    private int mLastDH;
41    private boolean mDrawNeeded;
42    private final int mThickness = 20;
43
44    public StrictModeFlash(Display display, SurfaceSession session) {
45        SurfaceControl ctrl = null;
46        try {
47            ctrl = new SurfaceControl(session, "StrictModeFlash",
48                1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
49            ctrl.setLayerStack(display.getLayerStack());
50            ctrl.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 101);  // one more than Watermark? arbitrary.
51            ctrl.setPosition(0, 0);
52            ctrl.show();
53            mSurface.copyFrom(ctrl);
54        } catch (OutOfResourcesException e) {
55        }
56        mSurfaceControl = ctrl;
57        mDrawNeeded = true;
58    }
59
60    private void drawIfNeeded() {
61        if (!mDrawNeeded) {
62            return;
63        }
64        mDrawNeeded = false;
65        final int dw = mLastDW;
66        final int dh = mLastDH;
67
68        Rect dirty = new Rect(0, 0, dw, dh);
69        Canvas c = null;
70        try {
71            c = mSurface.lockCanvas(dirty);
72        } catch (IllegalArgumentException e) {
73        } catch (Surface.OutOfResourcesException e) {
74        }
75        if (c == null) {
76            return;
77        }
78
79        // Top
80        c.clipRect(new Rect(0, 0, dw, mThickness), Region.Op.REPLACE);
81        c.drawColor(Color.RED);
82        // Left
83        c.clipRect(new Rect(0, 0, mThickness, dh), Region.Op.REPLACE);
84        c.drawColor(Color.RED);
85        // Right
86        c.clipRect(new Rect(dw - mThickness, 0, dw, dh), Region.Op.REPLACE);
87        c.drawColor(Color.RED);
88        // Bottom
89        c.clipRect(new Rect(0, dh - mThickness, dw, dh), Region.Op.REPLACE);
90        c.drawColor(Color.RED);
91
92        mSurface.unlockCanvasAndPost(c);
93    }
94
95    // Note: caller responsible for being inside
96    // Surface.openTransaction() / closeTransaction()
97    public void setVisibility(boolean on) {
98        if (mSurfaceControl == null) {
99            return;
100        }
101        drawIfNeeded();
102        if (on) {
103            mSurfaceControl.show();
104        } else {
105            mSurfaceControl.hide();
106        }
107    }
108
109    void positionSurface(int dw, int dh) {
110        if (mLastDW == dw && mLastDH == dh) {
111            return;
112        }
113        mLastDW = dw;
114        mLastDH = dh;
115        mSurfaceControl.setSize(dw, dh);
116        mDrawNeeded = true;
117    }
118
119}
120