blob: ae41541310799dbb1efc1d4770554fe5a5fcc607 [file] [log] [blame]
Prashant Malania04ea612014-07-18 17:27:56 -07001/*
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
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080020import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
21import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
22import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Prashant Malania04ea612014-07-18 17:27:56 -070023
24import android.graphics.Canvas;
25import android.graphics.Color;
26import android.graphics.Paint;
27import android.graphics.PixelFormat;
28import android.graphics.Point;
29import android.graphics.PorterDuff;
Prashant Malaniea481be2015-01-07 18:30:27 -080030import android.graphics.PorterDuffXfermode;
Prashant Malania04ea612014-07-18 17:27:56 -070031import android.graphics.Rect;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080032import android.util.Slog;
Prashant Malania04ea612014-07-18 17:27:56 -070033import android.view.Display;
34import android.view.Surface;
35import android.view.Surface.OutOfResourcesException;
36import android.view.SurfaceControl;
37import android.view.SurfaceSession;
Prashant Malania04ea612014-07-18 17:27:56 -070038
39class CircularDisplayMask {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080040 private static final String TAG = TAG_WITH_CLASS_NAME ? "CircularDisplayMask" : TAG_WM;
Prashant Malania04ea612014-07-18 17:27:56 -070041
Prashant Malania04ea612014-07-18 17:27:56 -070042 // size of the chin
43 private int mScreenOffset = 0;
44 // Display dimensions
45 private Point mScreenSize;
46
47 private final SurfaceControl mSurfaceControl;
48 private final Surface mSurface = new Surface();
49 private int mLastDW;
50 private int mLastDH;
51 private boolean mDrawNeeded;
52 private Paint mPaint;
53 private int mRotation;
54 private boolean mVisible;
55 private boolean mDimensionsUnequal = false;
Prashant Malania98c21a2015-02-10 19:09:39 -080056 private int mMaskThickness;
Prashant Malania04ea612014-07-18 17:27:56 -070057
58 public CircularDisplayMask(Display display, SurfaceSession session, int zOrder,
Prashant Malania98c21a2015-02-10 19:09:39 -080059 int screenOffset, int maskThickness) {
Prashant Malania04ea612014-07-18 17:27:56 -070060 mScreenSize = new Point();
61 display.getSize(mScreenSize);
Ching Tzung Lin9c57af42015-10-22 15:02:57 -070062 if (mScreenSize.x != mScreenSize.y + screenOffset) {
Prashant Malania04ea612014-07-18 17:27:56 -070063 Slog.w(TAG, "Screen dimensions of displayId = " + display.getDisplayId() +
64 "are not equal, circularMask will not be drawn.");
65 mDimensionsUnequal = true;
66 }
67
68 SurfaceControl ctrl = null;
69 try {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080070 if (DEBUG_SURFACE_TRACE) {
Robert Carre6a83512015-11-03 16:09:21 -080071 ctrl = new WindowSurfaceController.SurfaceTrace(session, "CircularDisplayMask",
Griff Hazen7fb61462014-09-08 21:34:52 -070072 mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT,
73 SurfaceControl.HIDDEN);
74 } else {
75 ctrl = new SurfaceControl(session, "CircularDisplayMask", mScreenSize.x,
76 mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
77 }
Prashant Malania04ea612014-07-18 17:27:56 -070078 ctrl.setLayerStack(display.getLayerStack());
79 ctrl.setLayer(zOrder);
80 ctrl.setPosition(0, 0);
81 ctrl.show();
82 mSurface.copyFrom(ctrl);
83 } catch (OutOfResourcesException e) {
84 }
85 mSurfaceControl = ctrl;
86 mDrawNeeded = true;
87 mPaint = new Paint();
88 mPaint.setAntiAlias(true);
Prashant Malaniea481be2015-01-07 18:30:27 -080089 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
Prashant Malania04ea612014-07-18 17:27:56 -070090 mScreenOffset = screenOffset;
Prashant Malania98c21a2015-02-10 19:09:39 -080091 mMaskThickness = maskThickness;
Prashant Malania04ea612014-07-18 17:27:56 -070092 }
93
94 private void drawIfNeeded() {
95 if (!mDrawNeeded || !mVisible || mDimensionsUnequal) {
96 return;
97 }
98 mDrawNeeded = false;
99
100 Rect dirty = new Rect(0, 0, mScreenSize.x, mScreenSize.y);
101 Canvas c = null;
102 try {
103 c = mSurface.lockCanvas(dirty);
104 } catch (IllegalArgumentException e) {
105 } catch (Surface.OutOfResourcesException e) {
106 }
107 if (c == null) {
108 return;
109 }
Prashant Malania04ea612014-07-18 17:27:56 -0700110 switch (mRotation) {
111 case Surface.ROTATION_0:
112 case Surface.ROTATION_90:
113 // chin bottom or right
114 mSurfaceControl.setPosition(0, 0);
115 break;
116 case Surface.ROTATION_180:
117 // chin top
118 mSurfaceControl.setPosition(0, -mScreenOffset);
119 break;
120 case Surface.ROTATION_270:
121 // chin left
122 mSurfaceControl.setPosition(-mScreenOffset, 0);
123 break;
124 }
125
126 int circleRadius = mScreenSize.x / 2;
Prashant Malaniea481be2015-01-07 18:30:27 -0800127 c.drawColor(Color.BLACK);
128
Prashant Malania98c21a2015-02-10 19:09:39 -0800129 // The radius is reduced by mMaskThickness to provide an anti aliasing effect on the display edges.
130 c.drawCircle(circleRadius, circleRadius, circleRadius - mMaskThickness, mPaint);
Prashant Malania04ea612014-07-18 17:27:56 -0700131 mSurface.unlockCanvasAndPost(c);
132 }
133
134 // Note: caller responsible for being inside
135 // Surface.openTransaction() / closeTransaction()
136 public void setVisibility(boolean on) {
137 if (mSurfaceControl == null) {
138 return;
139 }
140 mVisible = on;
141 drawIfNeeded();
142 if (on) {
143 mSurfaceControl.show();
144 } else {
145 mSurfaceControl.hide();
146 }
147 }
148
149 void positionSurface(int dw, int dh, int rotation) {
150 if (mLastDW == dw && mLastDH == dh && mRotation == rotation) {
151 return;
152 }
153 mLastDW = dw;
154 mLastDH = dh;
155 mDrawNeeded = true;
156 mRotation = rotation;
157 drawIfNeeded();
158 }
159
160}