Home | History | Annotate | Download | only in wm
      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