FocusedStackFrame.java revision 9158825f9c41869689d6b1786d7c7aa8bdd524ce
1/*
2 * Copyright (C) 2013 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.WindowManagerService.DEBUG_STACK;
20import static com.android.server.wm.WindowManagerService.DEBUG_SURFACE_TRACE;
21
22import android.graphics.Canvas;
23import android.graphics.Color;
24import android.graphics.PixelFormat;
25import android.graphics.Rect;
26import android.graphics.Region;
27import android.util.Slog;
28import android.view.Display;
29import android.view.Surface.OutOfResourcesException;
30import android.view.Surface;
31import android.view.SurfaceControl;
32import android.view.SurfaceSession;
33
34import com.android.server.wm.WindowStateAnimator.SurfaceTrace;
35
36class FocusedStackFrame {
37    private static final String TAG = "FocusedStackFrame";
38    private static final int THICKNESS = 10;
39    private static final float ALPHA = 0.3f;
40
41    private final SurfaceControl mSurfaceControl;
42    private final Surface mSurface = new Surface();
43    private final Rect mLastBounds = new Rect();
44    final Rect mBounds = new Rect();
45    private final Rect mTmpDrawRect = new Rect();
46
47    public FocusedStackFrame(Display display, SurfaceSession session) {
48        SurfaceControl ctrl = null;
49        try {
50            if (DEBUG_SURFACE_TRACE) {
51                ctrl = new SurfaceTrace(session, "FocusedStackFrame",
52                    1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
53            } else {
54                ctrl = new SurfaceControl(session, "FocusedStackFrame",
55                    1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
56            }
57            ctrl.setLayerStack(display.getLayerStack());
58            ctrl.setAlpha(ALPHA);
59            mSurface.copyFrom(ctrl);
60        } catch (OutOfResourcesException e) {
61        }
62        mSurfaceControl = ctrl;
63    }
64
65    private void draw(Rect bounds, int color) {
66        if (false && DEBUG_STACK) Slog.i(TAG, "draw: bounds=" + bounds.toShortString() +
67                " color=" + Integer.toHexString(color));
68        mTmpDrawRect.set(bounds);
69        Canvas c = null;
70        try {
71            c = mSurface.lockCanvas(mTmpDrawRect);
72        } catch (IllegalArgumentException e) {
73        } catch (Surface.OutOfResourcesException e) {
74        }
75        if (c == null) {
76            return;
77        }
78
79        final int w = bounds.width();
80        final int h = bounds.height();
81
82        // Top
83        mTmpDrawRect.set(0, 0, w, THICKNESS);
84        c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
85        c.drawColor(color);
86        // Left (not including Top or Bottom stripe).
87        mTmpDrawRect.set(0, THICKNESS, THICKNESS, h - THICKNESS);
88        c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
89        c.drawColor(color);
90        // Right (not including Top or Bottom stripe).
91        mTmpDrawRect.set(w - THICKNESS, THICKNESS, w, h - THICKNESS);
92        c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
93        c.drawColor(color);
94        // Bottom
95        mTmpDrawRect.set(0, h - THICKNESS, w, h);
96        c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
97        c.drawColor(color);
98
99        mSurface.unlockCanvasAndPost(c);
100    }
101
102    private void positionSurface(Rect bounds) {
103        if (false && DEBUG_STACK) Slog.i(TAG, "positionSurface: bounds=" + bounds.toShortString());
104        mSurfaceControl.setSize(bounds.width(), bounds.height());
105        mSurfaceControl.setPosition(bounds.left, bounds.top);
106    }
107
108    // Note: caller responsible for being inside
109    // Surface.openTransaction() / closeTransaction()
110    public void setVisibility(boolean on) {
111        if (false && DEBUG_STACK) Slog.i(TAG, "setVisibility: on=" + on +
112                " mLastBounds=" + mLastBounds.toShortString() +
113                " mBounds=" + mBounds.toShortString());
114        if (mSurfaceControl == null) {
115            return;
116        }
117        if (on) {
118            if (!mLastBounds.equals(mBounds)) {
119                // Erase the previous rectangle.
120                positionSurface(mLastBounds);
121                draw(mLastBounds, Color.TRANSPARENT);
122                // Draw the latest rectangle.
123                positionSurface(mBounds);
124                draw(mBounds, Color.WHITE);
125                // Update the history.
126                mLastBounds.set(mBounds);
127            }
128            mSurfaceControl.show();
129        } else {
130            mSurfaceControl.hide();
131        }
132    }
133
134    public void setBounds(TaskStack stack) {
135        stack.getBounds(mBounds);
136        if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + mBounds);
137    }
138
139    public void setLayer(int layer) {
140        mSurfaceControl.setLayer(layer);
141    }
142}
143