1a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner/*
2a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner * Copyright (C) 2013 The Android Open Source Project
3a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner *
4a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner * Licensed under the Apache License, Version 2.0 (the "License");
5a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner * you may not use this file except in compliance with the License.
6a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner * You may obtain a copy of the License at
7a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner *
8a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner *      http://www.apache.org/licenses/LICENSE-2.0
9a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner *
10a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner * Unless required by applicable law or agreed to in writing, software
11a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner * distributed under the License is distributed on an "AS IS" BASIS,
12a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner * See the License for the specific language governing permissions and
14a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner * limitations under the License.
15a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner */
16a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
17a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerpackage com.android.server.wm;
18a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
19a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport static com.android.server.wm.WindowManagerService.DEBUG_STACK;
20f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautnerimport static com.android.server.wm.WindowManagerService.DEBUG_SURFACE_TRACE;
21a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
22a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport android.graphics.Canvas;
23a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport android.graphics.Color;
24a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport android.graphics.PixelFormat;
25a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport android.graphics.Rect;
26a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport android.graphics.Region;
27a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport android.util.Slog;
28a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport android.view.Display;
29a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkinimport android.view.Surface.OutOfResourcesException;
30a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport android.view.Surface;
31a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport android.view.SurfaceControl;
32a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport android.view.SurfaceSession;
33a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
34f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautnerimport com.android.server.wm.WindowStateAnimator.SurfaceTrace;
35f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautner
36a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerclass FocusedStackFrame {
37a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    private static final String TAG = "FocusedStackFrame";
38a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    private static final int THICKNESS = 10;
39a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    private static final float ALPHA = 0.3f;
40a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
41a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    private final SurfaceControl mSurfaceControl;
42a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    private final Surface mSurface = new Surface();
43a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin    private final Rect mLastBounds = new Rect();
44bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner    final Rect mBounds = new Rect();
45a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin    private final Rect mTmpDrawRect = new Rect();
46a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
47a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    public FocusedStackFrame(Display display, SurfaceSession session) {
48a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        SurfaceControl ctrl = null;
49a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        try {
50f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautner            if (DEBUG_SURFACE_TRACE) {
51f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautner                ctrl = new SurfaceTrace(session, "FocusedStackFrame",
52f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautner                    1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
53f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautner            } else {
54f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautner                ctrl = new SurfaceControl(session, "FocusedStackFrame",
55f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautner                    1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
56f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautner            }
57a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            ctrl.setLayerStack(display.getLayerStack());
58a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            ctrl.setAlpha(ALPHA);
59a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            mSurface.copyFrom(ctrl);
60a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin        } catch (OutOfResourcesException e) {
61a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        }
62a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        mSurfaceControl = ctrl;
63a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    }
64a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
65a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    private void draw(Rect bounds, int color) {
66e2dd83a5b428df5a6ef21c11e71d021c640d843fCraig Mautner        if (false && DEBUG_STACK) Slog.i(TAG, "draw: bounds=" + bounds.toShortString() +
67a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner                " color=" + Integer.toHexString(color));
68a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        mTmpDrawRect.set(bounds);
69a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        Canvas c = null;
70a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        try {
71a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            c = mSurface.lockCanvas(mTmpDrawRect);
72a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        } catch (IllegalArgumentException e) {
73a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        } catch (Surface.OutOfResourcesException e) {
74a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        }
75a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        if (c == null) {
76a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            return;
77a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        }
78a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
79a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        final int w = bounds.width();
80a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        final int h = bounds.height();
81a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
82a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        // Top
83a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        mTmpDrawRect.set(0, 0, w, THICKNESS);
84a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
85a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        c.drawColor(color);
86a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        // Left (not including Top or Bottom stripe).
87a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        mTmpDrawRect.set(0, THICKNESS, THICKNESS, h - THICKNESS);
88a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
89a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        c.drawColor(color);
90a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        // Right (not including Top or Bottom stripe).
91a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        mTmpDrawRect.set(w - THICKNESS, THICKNESS, w, h - THICKNESS);
92a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
93a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        c.drawColor(color);
94a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        // Bottom
95a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        mTmpDrawRect.set(0, h - THICKNESS, w, h);
96a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
97a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        c.drawColor(color);
98a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
99a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        mSurface.unlockCanvasAndPost(c);
100a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    }
101a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
102a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    private void positionSurface(Rect bounds) {
103e2dd83a5b428df5a6ef21c11e71d021c640d843fCraig Mautner        if (false && DEBUG_STACK) Slog.i(TAG, "positionSurface: bounds=" + bounds.toShortString());
104a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        mSurfaceControl.setSize(bounds.width(), bounds.height());
105a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        mSurfaceControl.setPosition(bounds.left, bounds.top);
106a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    }
107a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
108a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    // Note: caller responsible for being inside
109a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    // Surface.openTransaction() / closeTransaction()
110a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    public void setVisibility(boolean on) {
111e2dd83a5b428df5a6ef21c11e71d021c640d843fCraig Mautner        if (false && DEBUG_STACK) Slog.i(TAG, "setVisibility: on=" + on +
112a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner                " mLastBounds=" + mLastBounds.toShortString() +
113a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner                " mBounds=" + mBounds.toShortString());
114a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        if (mSurfaceControl == null) {
115a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            return;
116a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        }
117a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        if (on) {
118a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            if (!mLastBounds.equals(mBounds)) {
119a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner                // Erase the previous rectangle.
120a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner                positionSurface(mLastBounds);
121a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner                draw(mLastBounds, Color.TRANSPARENT);
122a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner                // Draw the latest rectangle.
123a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner                positionSurface(mBounds);
124a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner                draw(mBounds, Color.WHITE);
125a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner                // Update the history.
126a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner                mLastBounds.set(mBounds);
127a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            }
128a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            mSurfaceControl.show();
129a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        } else {
130a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            mSurfaceControl.hide();
131a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        }
132a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    }
133a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner
134bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner    public void setBounds(TaskStack stack) {
135bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner        stack.getBounds(mBounds);
136bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner        if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + mBounds);
137a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner    }
138f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautner
139f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautner    public void setLayer(int layer) {
140f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautner        mSurfaceControl.setLayer(layer);
141f76664673eed1c7b2fa141ce99e01028bc7a1be0Craig Mautner    }
142a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner}
143