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