summaryrefslogtreecommitdiffstats
path: root/services/core/java/com/android/server/wm/DimLayer.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/core/java/com/android/server/wm/DimLayer.java')
-rw-r--r--services/core/java/com/android/server/wm/DimLayer.java290
1 files changed, 290 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java
new file mode 100644
index 0000000..978d5b7
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DimLayer.java
@@ -0,0 +1,290 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+package com.android.server.wm;
+
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.view.DisplayInfo;
+import android.view.SurfaceControl;
+
+import java.io.PrintWriter;
+
+public class DimLayer {
+ private static final String TAG = "DimLayer";
+ private static final boolean DEBUG = false;
+
+ /** Reference to the owner of this object. */
+ final DisplayContent mDisplayContent;
+
+ /** Actual surface that dims */
+ SurfaceControl mDimSurface;
+
+ /** Last value passed to mDimSurface.setAlpha() */
+ float mAlpha = 0;
+
+ /** Last value passed to mDimSurface.setLayer() */
+ int mLayer = -1;
+
+ /** Next values to pass to mDimSurface.setPosition() and mDimSurface.setSize() */
+ Rect mBounds = new Rect();
+
+ /** Last values passed to mDimSurface.setPosition() and mDimSurface.setSize() */
+ Rect mLastBounds = new Rect();
+
+ /** True after mDimSurface.show() has been called, false after mDimSurface.hide(). */
+ private boolean mShowing = false;
+
+ /** Value of mAlpha when beginning transition to mTargetAlpha */
+ float mStartAlpha = 0;
+
+ /** Final value of mAlpha following transition */
+ float mTargetAlpha = 0;
+
+ /** Time in units of SystemClock.uptimeMillis() at which the current transition started */
+ long mStartTime;
+
+ /** Time in milliseconds to take to transition from mStartAlpha to mTargetAlpha */
+ long mDuration;
+
+ /** Owning stack */
+ final TaskStack mStack;
+
+ DimLayer(WindowManagerService service, TaskStack stack) {
+ mStack = stack;
+ mDisplayContent = stack.getDisplayContent();
+ final int displayId = mDisplayContent.getDisplayId();
+ if (DEBUG) Slog.v(TAG, "Ctor: displayId=" + displayId);
+ SurfaceControl.openTransaction();
+ try {
+ if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+ mDimSurface = new WindowStateAnimator.SurfaceTrace(service.mFxSession,
+ "DimSurface",
+ 16, 16, PixelFormat.OPAQUE,
+ SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
+ } else {
+ mDimSurface = new SurfaceControl(service.mFxSession, TAG,
+ 16, 16, PixelFormat.OPAQUE,
+ SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
+ }
+ if (WindowManagerService.SHOW_TRANSACTIONS ||
+ WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(TAG,
+ " DIM " + mDimSurface + ": CREATE");
+ mDimSurface.setLayerStack(displayId);
+ } catch (Exception e) {
+ Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+
+ /** Return true if dim layer is showing */
+ boolean isDimming() {
+ return mTargetAlpha != 0;
+ }
+
+ /** Return true if in a transition period */
+ boolean isAnimating() {
+ return mTargetAlpha != mAlpha;
+ }
+
+ float getTargetAlpha() {
+ return mTargetAlpha;
+ }
+
+ void setLayer(int layer) {
+ if (mLayer != layer) {
+ mLayer = layer;
+ mDimSurface.setLayer(layer);
+ }
+ }
+
+ int getLayer() {
+ return mLayer;
+ }
+
+ private void setAlpha(float alpha) {
+ if (mAlpha != alpha) {
+ if (DEBUG) Slog.v(TAG, "setAlpha alpha=" + alpha);
+ try {
+ mDimSurface.setAlpha(alpha);
+ if (alpha == 0 && mShowing) {
+ if (DEBUG) Slog.v(TAG, "setAlpha hiding");
+ mDimSurface.hide();
+ mShowing = false;
+ } else if (alpha > 0 && !mShowing) {
+ if (DEBUG) Slog.v(TAG, "setAlpha showing");
+ mDimSurface.show();
+ mShowing = true;
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure setting alpha immediately", e);
+ }
+ mAlpha = alpha;
+ }
+ }
+
+ void setBounds(Rect bounds) {
+ mBounds.set(bounds);
+ }
+
+ /**
+ * @param duration The time to test.
+ * @return True if the duration would lead to an earlier end to the current animation.
+ */
+ private boolean durationEndsEarlier(long duration) {
+ return SystemClock.uptimeMillis() + duration < mStartTime + mDuration;
+ }
+
+ /** Jump to the end of the animation.
+ * NOTE: Must be called with Surface transaction open. */
+ void show() {
+ if (isAnimating()) {
+ if (DEBUG) Slog.v(TAG, "show: immediate");
+ show(mLayer, mTargetAlpha, 0);
+ }
+ }
+
+ /**
+ * Begin an animation to a new dim value.
+ * NOTE: Must be called with Surface transaction open.
+ *
+ * @param layer The layer to set the surface to.
+ * @param alpha The dim value to end at.
+ * @param duration How long to take to get there in milliseconds.
+ */
+ void show(int layer, float alpha, long duration) {
+ if (DEBUG) Slog.v(TAG, "show: layer=" + layer + " alpha=" + alpha
+ + " duration=" + duration);
+ if (mDimSurface == null) {
+ Slog.e(TAG, "show: no Surface");
+ // Make sure isAnimating() returns false.
+ mTargetAlpha = mAlpha = 0;
+ return;
+ }
+
+ final int dw, dh;
+ final float xPos, yPos;
+ if (!mStack.isFullscreen()) {
+ dw = mBounds.width();
+ dh = mBounds.height();
+ xPos = mBounds.left;
+ yPos = mBounds.right;
+ } else {
+ // Set surface size to screen size.
+ final DisplayInfo info = mDisplayContent.getDisplayInfo();
+ // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose a
+ // corner.
+ dw = (int) (info.logicalWidth * 1.5);
+ dh = (int) (info.logicalHeight * 1.5);
+ // back off position so 1/4 of Surface is before and 1/4 is after.
+ xPos = -1 * dw / 6;
+ yPos = -1 * dh / 6;
+ }
+
+ if (!mLastBounds.equals(mBounds) || mLayer != layer) {
+ try {
+ mDimSurface.setPosition(xPos, yPos);
+ mDimSurface.setSize(dw, dh);
+ mDimSurface.setLayer(layer);
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure setting size or layer", e);
+ }
+ mLastBounds.set(mBounds);
+ mLayer = layer;
+ }
+
+ long curTime = SystemClock.uptimeMillis();
+ final boolean animating = isAnimating();
+ if ((animating && (mTargetAlpha != alpha || durationEndsEarlier(duration)))
+ || (!animating && mAlpha != alpha)) {
+ if (duration <= 0) {
+ // No animation required, just set values.
+ setAlpha(alpha);
+ } else {
+ // Start or continue animation with new parameters.
+ mStartAlpha = mAlpha;
+ mStartTime = curTime;
+ mDuration = duration;
+ }
+ }
+ if (DEBUG) Slog.v(TAG, "show: mStartAlpha=" + mStartAlpha + " mStartTime=" + mStartTime);
+ mTargetAlpha = alpha;
+ }
+
+ /** Immediate hide.
+ * NOTE: Must be called with Surface transaction open. */
+ void hide() {
+ if (mShowing) {
+ if (DEBUG) Slog.v(TAG, "hide: immediate");
+ hide(0);
+ }
+ }
+
+ /**
+ * Gradually fade to transparent.
+ * NOTE: Must be called with Surface transaction open.
+ *
+ * @param duration Time to fade in milliseconds.
+ */
+ void hide(long duration) {
+ if (mShowing && (mTargetAlpha != 0 || durationEndsEarlier(duration))) {
+ if (DEBUG) Slog.v(TAG, "hide: duration=" + duration);
+ show(mLayer, 0, duration);
+ }
+ }
+
+ /**
+ * Advance the dimming per the last #show(int, float, long) call.
+ * NOTE: Must be called with Surface transaction open.
+ *
+ * @return True if animation is still required after this step.
+ */
+ boolean stepAnimation() {
+ if (mDimSurface == null) {
+ Slog.e(TAG, "stepAnimation: null Surface");
+ // Ensure that isAnimating() returns false;
+ mTargetAlpha = mAlpha = 0;
+ return false;
+ }
+
+ if (isAnimating()) {
+ final long curTime = SystemClock.uptimeMillis();
+ final float alphaDelta = mTargetAlpha - mStartAlpha;
+ float alpha = mStartAlpha + alphaDelta * (curTime - mStartTime) / mDuration;
+ if (alphaDelta > 0 && alpha > mTargetAlpha ||
+ alphaDelta < 0 && alpha < mTargetAlpha) {
+ // Don't exceed limits.
+ alpha = mTargetAlpha;
+ }
+ if (DEBUG) Slog.v(TAG, "stepAnimation: curTime=" + curTime + " alpha=" + alpha);
+ setAlpha(alpha);
+ }
+
+ return isAnimating();
+ }
+
+ /** Cleanup */
+ void destroySurface() {
+ if (DEBUG) Slog.v(TAG, "destroySurface.");
+ if (mDimSurface != null) {
+ mDimSurface.destroy();
+ mDimSurface = null;
+ }
+ }
+
+ public void printTo(String prefix, PrintWriter pw) {
+ pw.print(prefix); pw.print("mDimSurface="); pw.print(mDimSurface);
+ pw.print(" mLayer="); pw.print(mLayer);
+ pw.print(" mAlpha="); pw.println(mAlpha);
+ pw.print(prefix); pw.print("mLastBounds="); pw.print(mLastBounds.toShortString());
+ pw.print(" mBounds="); pw.println(mBounds.toShortString());
+ pw.print(prefix); pw.print("Last animation: ");
+ pw.print(" mDuration="); pw.print(mDuration);
+ pw.print(" mStartTime="); pw.print(mStartTime);
+ pw.print(" curTime="); pw.println(SystemClock.uptimeMillis());
+ pw.print(prefix); pw.print(" mStartAlpha="); pw.print(mStartAlpha);
+ pw.print(" mTargetAlpha="); pw.println(mTargetAlpha);
+ }
+}