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 17 package com.android.server.wm; 18 19 import static com.android.server.wm.WindowManagerService.DEBUG_STACK; 20 import static com.android.server.wm.WindowManagerService.DEBUG_SURFACE_TRACE; 21 22 import android.graphics.Canvas; 23 import android.graphics.Color; 24 import android.graphics.PixelFormat; 25 import android.graphics.Rect; 26 import android.graphics.Region; 27 import android.util.Slog; 28 import android.view.Display; 29 import android.view.Surface.OutOfResourcesException; 30 import android.view.Surface; 31 import android.view.SurfaceControl; 32 import android.view.SurfaceSession; 33 34 import com.android.server.wm.WindowStateAnimator.SurfaceTrace; 35 36 class 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 private 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(Rect bounds) { 135 if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + bounds); 136 mBounds.set(bounds); 137 } 138 139 public void setLayer(int layer) { 140 mSurfaceControl.setLayer(layer); 141 } 142 } 143