CircularDisplayMask.java revision a04ea61db5566f05d5c783b2f62614aa03005be9
1/* 2 * Copyright (C) 2014 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 20 21import android.graphics.Canvas; 22import android.graphics.Color; 23import android.graphics.Paint; 24import android.graphics.PixelFormat; 25import android.graphics.Point; 26import android.graphics.PorterDuff; 27import android.graphics.Rect; 28import android.view.Display; 29import android.view.Surface; 30import android.view.Surface.OutOfResourcesException; 31import android.view.SurfaceControl; 32import android.view.SurfaceSession; 33import android.util.Slog; 34 35class CircularDisplayMask { 36 private static final String TAG = "CircularDisplayMask"; 37 38 private static final int STROKE_WIDTH = 2; 39 // size of the chin 40 private int mScreenOffset = 0; 41 // Display dimensions 42 private Point mScreenSize; 43 44 private final SurfaceControl mSurfaceControl; 45 private final Surface mSurface = new Surface(); 46 private int mLastDW; 47 private int mLastDH; 48 private boolean mDrawNeeded; 49 private Paint mPaint; 50 private int mRotation; 51 private boolean mVisible; 52 private boolean mDimensionsUnequal = false; 53 54 public CircularDisplayMask(Display display, SurfaceSession session, int zOrder, 55 int screenOffset) { 56 mScreenSize = new Point(); 57 display.getSize(mScreenSize); 58 if (mScreenSize.x != mScreenSize.y) { 59 Slog.w(TAG, "Screen dimensions of displayId = " + display.getDisplayId() + 60 "are not equal, circularMask will not be drawn."); 61 mDimensionsUnequal = true; 62 } 63 64 SurfaceControl ctrl = null; 65 try { 66 ctrl = new SurfaceControl(session, "CircularDisplayMask", 67 mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 68 ctrl.setLayerStack(display.getLayerStack()); 69 ctrl.setLayer(zOrder); 70 ctrl.setPosition(0, 0); 71 ctrl.show(); 72 mSurface.copyFrom(ctrl); 73 } catch (OutOfResourcesException e) { 74 } 75 mSurfaceControl = ctrl; 76 mDrawNeeded = true; 77 mPaint = new Paint(); 78 mPaint.setAntiAlias(true); 79 mPaint.setStyle(Paint.Style.STROKE); 80 mPaint.setColor(Color.BLACK); 81 mPaint.setStrokeWidth(STROKE_WIDTH); 82 mScreenOffset = screenOffset; 83 } 84 85 private void drawIfNeeded() { 86 if (!mDrawNeeded || !mVisible || mDimensionsUnequal) { 87 return; 88 } 89 mDrawNeeded = false; 90 91 Rect dirty = new Rect(0, 0, mScreenSize.x, mScreenSize.y); 92 Canvas c = null; 93 try { 94 c = mSurface.lockCanvas(dirty); 95 } catch (IllegalArgumentException e) { 96 } catch (Surface.OutOfResourcesException e) { 97 } 98 if (c == null) { 99 return; 100 } 101 c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC); 102 switch (mRotation) { 103 case Surface.ROTATION_0: 104 case Surface.ROTATION_90: 105 // chin bottom or right 106 mSurfaceControl.setPosition(0, 0); 107 break; 108 case Surface.ROTATION_180: 109 // chin top 110 mSurfaceControl.setPosition(0, -mScreenOffset); 111 break; 112 case Surface.ROTATION_270: 113 // chin left 114 mSurfaceControl.setPosition(-mScreenOffset, 0); 115 break; 116 } 117 118 int circleRadius = mScreenSize.x / 2; 119 c.drawCircle(circleRadius, circleRadius, circleRadius, mPaint); 120 mSurface.unlockCanvasAndPost(c); 121 } 122 123 // Note: caller responsible for being inside 124 // Surface.openTransaction() / closeTransaction() 125 public void setVisibility(boolean on) { 126 if (mSurfaceControl == null) { 127 return; 128 } 129 mVisible = on; 130 drawIfNeeded(); 131 if (on) { 132 mSurfaceControl.show(); 133 } else { 134 mSurfaceControl.hide(); 135 } 136 } 137 138 void positionSurface(int dw, int dh, int rotation) { 139 if (mLastDW == dw && mLastDH == dh && mRotation == rotation) { 140 return; 141 } 142 mLastDW = dw; 143 mLastDH = dh; 144 mDrawNeeded = true; 145 mRotation = rotation; 146 drawIfNeeded(); 147 } 148 149} 150