diff options
-rw-r--r-- | services/core/java/com/android/server/wm/CircularDisplayMask.java | 110 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 45 |
2 files changed, 155 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java new file mode 100644 index 0000000..fbfca93 --- /dev/null +++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.util.Log; +import android.view.Display; +import android.view.Surface; +import android.view.Surface.OutOfResourcesException; +import android.view.SurfaceControl; +import android.view.SurfaceSession; + +class CircularDisplayMask { + private static final String TAG = "CircularDisplayMask"; + + private static final int STROKE_WIDTH = 2; + + private final SurfaceControl mSurfaceControl; + private final Surface mSurface = new Surface(); + private int mLastDW; + private int mLastDH; + private boolean mDrawNeeded; + private Paint mPaint; + + public CircularDisplayMask(Display display, SurfaceSession session, int zOrder) { + SurfaceControl ctrl = null; + try { + ctrl = new SurfaceControl(session, "CircularDisplayMask", + 320, 290, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); + ctrl.setLayerStack(display.getLayerStack()); + ctrl.setLayer(zOrder); + ctrl.setPosition(0, 0); + ctrl.show(); + mSurface.copyFrom(ctrl); + } catch (OutOfResourcesException e) { + } + mSurfaceControl = ctrl; + mDrawNeeded = true; + mPaint = new Paint(); + mPaint.setAntiAlias(true); + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setColor(Color.BLACK); + mPaint.setStrokeWidth(STROKE_WIDTH); + } + + private void drawIfNeeded() { + if (!mDrawNeeded) { + return; + } + mDrawNeeded = false; + + Rect dirty = new Rect(0, 0, mLastDW, mLastDH); + Canvas c = null; + try { + c = mSurface.lockCanvas(dirty); + } catch (IllegalArgumentException e) { + } catch (Surface.OutOfResourcesException e) { + } + if (c == null) { + return; + } + c.drawCircle(160, 160, 160, mPaint); + + mSurface.unlockCanvasAndPost(c); + } + + // Note: caller responsible for being inside + // Surface.openTransaction() / closeTransaction() + public void setVisibility(boolean on) { + if (mSurfaceControl == null) { + return; + } + drawIfNeeded(); + if (on) { + mSurfaceControl.show(); + } else { + mSurfaceControl.hide(); + } + } + + void positionSurface(int dw, int dh) { + if (mLastDW == dw && mLastDH == dh) { + return; + } + mLastDW = dw; + mLastDH = dh; + mSurfaceControl.setSize(dw, dh); + mDrawNeeded = true; + } + +} diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index dcf5880..f327a35 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -285,6 +285,8 @@ public class WindowManagerService extends IWindowManager.Stub private static final String DENSITY_OVERRIDE = "ro.config.density_override"; private static final String SIZE_OVERRIDE = "ro.config.size_override"; + private static final String SCREEN_CIRCULAR = "ro.display.circular"; + private static final int MAX_SCREENSHOT_RETRIES = 3; final private KeyguardDisableHandler mKeyguardDisableHandler; @@ -422,6 +424,7 @@ public class WindowManagerService extends IWindowManager.Stub final SurfaceSession mFxSession; Watermark mWatermark; StrictModeFlash mStrictModeFlash; + CircularDisplayMask mCircularDisplayMask; FocusedStackFrame mFocusedStackFrame; int mFocusedStackLayer; @@ -819,6 +822,7 @@ public class WindowManagerService extends IWindowManager.Stub } LocalServices.addService(WindowManagerInternal.class, new LocalService()); + showCircularDisplayMaskIfNeeded(); } public InputMonitor getInputMonitor() { @@ -5483,6 +5487,37 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void showCircularDisplayMaskIfNeeded() { + if (SystemProperties.getBoolean(SCREEN_CIRCULAR, false)) { + mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK)); + } + } + + public void showCircularMask() { + synchronized(mWindowMap) { + + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, + ">>> OPEN TRANSACTION showDisplayMask"); + SurfaceControl.openTransaction(); + try { + // TODO(multi-display): support multiple displays + if (mCircularDisplayMask == null) { + mCircularDisplayMask = new CircularDisplayMask( + getDefaultDisplayContentLocked().getDisplay(), + mFxSession, + mPolicy.windowTypeToLayerLw( + WindowManager.LayoutParams.TYPE_POINTER) + * TYPE_LAYER_MULTIPLIER + 10); + } + mCircularDisplayMask.setVisibility(true); + } finally { + SurfaceControl.closeTransaction(); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, + "<<< CLOSE TRANSACTION showDisplayMask"); + } + } + } + // TODO: more accounting of which pid(s) turned it on, keep count, // only allow disables from pids which have count on, etc. @Override @@ -7107,6 +7142,8 @@ public class WindowManagerService extends IWindowManager.Stub public static final int REMOVE_STARTING_TIMEOUT = 33; + public static final int SHOW_DISPLAY_MASK = 34; + @Override public void handleMessage(Message msg) { if (DEBUG_WINDOW_TRACE) { @@ -7502,6 +7539,11 @@ public class WindowManagerService extends IWindowManager.Stub break; } + case SHOW_DISPLAY_MASK: { + showCircularMask(); + break; + } + case DO_ANIMATION_CALLBACK: { try { ((IRemoteCallback)msg.obj).sendResult(null); @@ -8975,6 +9017,9 @@ public class WindowManagerService extends IWindowManager.Stub if (mStrictModeFlash != null) { mStrictModeFlash.positionSurface(defaultDw, defaultDh); } + if (mCircularDisplayMask != null) { + mCircularDisplayMask.positionSurface(defaultDw, defaultDh); + } boolean focusDisplayed = false; |