Fix lack of dim layer behind "Power off" window.
This enables dim behind functionality for both tasks and stacks and
groups it inside a controller that manages the dim layers (including
shared dim layers for full screen tasks/stacks).
Bug: 24331704
Change-Id: I0d1ba996d9e00d05e0203166b82268da00fbb35e
diff --git a/services/core/java/com/android/server/wm/DimBehindController.java b/services/core/java/com/android/server/wm/DimBehindController.java
new file mode 100644
index 0000000..c56af39
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DimBehindController.java
@@ -0,0 +1,291 @@
+package com.android.server.wm;
+
+import static com.android.server.wm.WindowManagerService.DEBUG_DIM_LAYER;
+
+import android.graphics.Rect;
+import android.util.ArrayMap;
+import android.util.Slog;
+import android.util.TypedValue;
+
+import java.io.PrintWriter;
+
+/**
+ * Centralizes the control of dim layers used for
+ * {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}.
+ */
+class DimBehindController {
+ private static final String TAG = "DimBehindController";
+
+ /** Amount of time in milliseconds to animate the dim surface from one value to another,
+ * when no window animation is driving it. */
+ private static final int DEFAULT_DIM_DURATION = 200;
+
+ // Shared dim layer for fullscreen users. {@link DimBehindState#dimLayer} will point to this
+ // instead of creating a new object per fullscreen task on a display.
+ private DimLayer mSharedFullScreenDimLayer;
+
+ private ArrayMap<DimLayer.DimLayerUser, DimBehindState> mState = new ArrayMap<>();
+
+ private DisplayContent mDisplayContent;
+
+ private Rect mTmpBounds = new Rect();
+
+ DimBehindController(DisplayContent displayContent) {
+ mDisplayContent = displayContent;
+ }
+
+ /** Updates the dim layer bounds, recreating it if needed. */
+ void updateDimLayer(DimLayer.DimLayerUser dimLayerUser) {
+ DimBehindState state = getOrCreateDimBehindState(dimLayerUser);
+ final boolean previousFullscreen = state.dimLayer != null
+ && state.dimLayer == mSharedFullScreenDimLayer;
+ DimLayer newDimLayer;
+ final int displayId = mDisplayContent.getDisplayId();
+ if (dimLayerUser.isFullscreen()) {
+ if (previousFullscreen) {
+ // Nothing to do here...
+ return;
+ }
+ // Use shared fullscreen dim layer
+ newDimLayer = mSharedFullScreenDimLayer;
+ if (newDimLayer == null) {
+ if (state.dimLayer != null) {
+ // Re-purpose the previous dim layer.
+ newDimLayer = state.dimLayer;
+ } else {
+ // Create new full screen dim layer.
+ newDimLayer = new DimLayer(mDisplayContent.mService, dimLayerUser, displayId);
+ }
+ dimLayerUser.getBounds(mTmpBounds);
+ newDimLayer.setBounds(mTmpBounds);
+ mSharedFullScreenDimLayer = newDimLayer;
+ } else if (state.dimLayer != null) {
+ state.dimLayer. destroySurface();
+ }
+ } else {
+ newDimLayer = (state.dimLayer == null || previousFullscreen)
+ ? new DimLayer(mDisplayContent.mService, dimLayerUser, displayId)
+ : state.dimLayer;
+ dimLayerUser.getBounds(mTmpBounds);
+ newDimLayer.setBounds(mTmpBounds);
+ }
+ state.dimLayer = newDimLayer;
+ }
+
+ private DimBehindState getOrCreateDimBehindState(DimLayer.DimLayerUser dimLayerUser) {
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "getDimBehindState, dimLayerUser="
+ + dimLayerUser.toShortString());
+ DimBehindState state = mState.get(dimLayerUser);
+ if (state == null) {
+ state = new DimBehindState();
+ mState.put(dimLayerUser, state);
+ }
+ return state;
+ }
+
+ private void setContinueDimming(DimLayer.DimLayerUser dimLayerUser) {
+ DimBehindState state = mState.get(dimLayerUser);
+ if (state == null) {
+ if (DEBUG_DIM_LAYER) Slog.w(TAG, "setContinueDimming, no state for: "
+ + dimLayerUser.toShortString());
+ return;
+ }
+ state.continueDimming = true;
+ }
+
+ boolean isDimming() {
+ for (int i = mState.size() - 1; i >= 0; i--) {
+ DimBehindState state = mState.valueAt(i);
+ if (state.dimLayer != null && state.dimLayer.isDimming()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void resetDimming() {
+ for (int i = mState.size() - 1; i >= 0; i--) {
+ mState.valueAt(i).continueDimming = false;
+ }
+ }
+
+ private boolean getContinueDimming(DimLayer.DimLayerUser dimLayerUser) {
+ DimBehindState state = mState.get(dimLayerUser);
+ return state != null && state.continueDimming;
+ }
+
+ void startDimmingIfNeeded(DimLayer.DimLayerUser dimLayerUser,
+ WindowStateAnimator newWinAnimator) {
+ // Only set dim params on the highest dimmed layer.
+ // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer.
+ DimBehindState state = getOrCreateDimBehindState(dimLayerUser);
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "startDimmingIfNeeded,"
+ + " dimLayerUser=" + dimLayerUser.toShortString()
+ + " newWinAnimator=" + newWinAnimator
+ + " state.animator=" + state.animator);
+ if (newWinAnimator.mSurfaceShown && (state.animator == null
+ || !state.animator.mSurfaceShown
+ || state.animator.mAnimLayer <= newWinAnimator.mAnimLayer)) {
+ state.animator = newWinAnimator;
+ if (state.animator.mWin.mAppToken == null && !dimLayerUser.isFullscreen()) {
+ // Dim should cover the entire screen for system windows.
+ mDisplayContent.getLogicalDisplayRect(mTmpBounds);
+ state.dimLayer.setBounds(mTmpBounds);
+ }
+ }
+ }
+
+ void stopDimmingIfNeeded() {
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "stopDimmingIfNeeded, mState.size()=" + mState.size());
+ for (int i = mState.size() - 1; i >= 0; i--) {
+ DimLayer.DimLayerUser dimLayerUser = mState.keyAt(i);
+ stopDimmingIfNeeded(dimLayerUser);
+ }
+ }
+
+ private void stopDimmingIfNeeded(DimLayer.DimLayerUser dimLayerUser) {
+ // No need to check if state is null, we know the key has a value.
+ DimBehindState state = mState.get(dimLayerUser);
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "stopDimmingIfNeeded,"
+ + " dimLayerUser=" + dimLayerUser.toShortString()
+ + " state.continueDimming=" + state.continueDimming
+ + " state.dimLayer.isDimming=" + state.dimLayer.isDimming());
+ if (!state.continueDimming && state.dimLayer.isDimming()) {
+ state.animator = null;
+ dimLayerUser.getBounds(mTmpBounds);
+ state.dimLayer.setBounds(mTmpBounds);
+ }
+ }
+
+ boolean animateDimLayers() {
+ int fullScreen = -1;
+ for (int i = mState.size() - 1; i >= 0; i--) {
+ DimLayer.DimLayerUser dimLayerUser = mState.keyAt(i);
+ if (dimLayerUser.isFullscreen()) {
+ fullScreen = i;
+ if (mState.valueAt(i).continueDimming) {
+ break;
+ }
+ }
+ }
+ if (fullScreen != -1) {
+ return animateDimLayers(mState.keyAt(fullScreen));
+ } else {
+ boolean result = false;
+ for (int i = mState.size() - 1; i >= 0; i--) {
+ result |= animateDimLayers(mState.keyAt(i));
+ }
+ return result;
+ }
+ }
+
+ private boolean animateDimLayers(DimLayer.DimLayerUser dimLayerUser) {
+ DimBehindState state = mState.get(dimLayerUser);
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "animateDimLayers,"
+ + " dimLayerUser=" + dimLayerUser.toShortString()
+ + " state.animator=" + state.animator
+ + " state.continueDimming=" + state.continueDimming);
+ final int dimLayer;
+ final float dimAmount;
+ if (state.animator == null) {
+ dimLayer = state.dimLayer.getLayer();
+ dimAmount = 0;
+ } else {
+ dimLayer = state.animator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM;
+ dimAmount = state.animator.mWin.mAttrs.dimAmount;
+ }
+ final float targetAlpha = state.dimLayer.getTargetAlpha();
+ if (targetAlpha != dimAmount) {
+ if (state.animator == null) {
+ state.dimLayer.hide(DEFAULT_DIM_DURATION);
+ } else {
+ long duration = (state.animator.mAnimating && state.animator.mAnimation != null)
+ ? state.animator.mAnimation.computeDurationHint()
+ : DEFAULT_DIM_DURATION;
+ if (targetAlpha > dimAmount) {
+ duration = getDimBehindFadeDuration(duration);
+ }
+ state.dimLayer.show(dimLayer, dimAmount, duration);
+ }
+ } else if (state.dimLayer.getLayer() != dimLayer) {
+ state.dimLayer.setLayer(dimLayer);
+ }
+ if (state.dimLayer.isAnimating()) {
+ if (!mDisplayContent.mService.okToDisplay()) {
+ // Jump to the end of the animation.
+ state.dimLayer.show();
+ } else {
+ return state.dimLayer.stepAnimation();
+ }
+ }
+ return false;
+ }
+
+ boolean isDimming(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator winAnimator) {
+ DimBehindState state = mState.get(dimLayerUser);
+ return state != null && state.animator == winAnimator && state.dimLayer.isDimming();
+ }
+
+ private long getDimBehindFadeDuration(long duration) {
+ TypedValue tv = new TypedValue();
+ mDisplayContent.mService.mContext.getResources().getValue(
+ com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true);
+ if (tv.type == TypedValue.TYPE_FRACTION) {
+ duration = (long) tv.getFraction(duration, duration);
+ } else if (tv.type >= TypedValue.TYPE_FIRST_INT && tv.type <= TypedValue.TYPE_LAST_INT) {
+ duration = tv.data;
+ }
+ return duration;
+ }
+
+ void close() {
+ for (int i = mState.size() - 1; i >= 0; i--) {
+ DimBehindState state = mState.valueAt(i);
+ state.dimLayer.destroySurface();
+ }
+ mState.clear();
+ mSharedFullScreenDimLayer = null;
+ }
+
+ void removeDimLayerUser(DimLayer.DimLayerUser dimLayerUser) {
+ mState.remove(dimLayerUser);
+ }
+
+ void applyDimBehind(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) {
+ if (dimLayerUser == null) {
+ Slog.e(TAG, "Trying to apply dim layer for: " + this
+ + ", but no dim layer user found.");
+ return;
+ }
+ if (!getContinueDimming(dimLayerUser)) {
+ setContinueDimming(dimLayerUser);
+ if (!isDimming(dimLayerUser, animator)) {
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "Win " + this + " start dimming.");
+ startDimmingIfNeeded(dimLayerUser, animator);
+ }
+ }
+ }
+
+ private static class DimBehindState {
+ // The particular window with FLAG_DIM_BEHIND set. If null, hide dimLayer.
+ WindowStateAnimator animator;
+ // Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the
+ // end then stop any dimming.
+ boolean continueDimming;
+ DimLayer dimLayer;
+ }
+
+ void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + "DimBehindController");
+ for (int i = 0, n = mState.size(); i < n; i++) {
+ pw.println(prefix + " " + mState.keyAt(i).toShortString());
+ pw.print(prefix + " ");
+ DimBehindState state = mState.valueAt(i);
+ pw.print("dimLayer=" + (state.dimLayer == mSharedFullScreenDimLayer ? "shared" :
+ state.dimLayer));
+ pw.print(", animator=" + state.animator);
+ pw.println(", continueDimming=" + state.continueDimming + "}");
+
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java
index 538d6b84..8c479d8 100644
--- a/services/core/java/com/android/server/wm/DimLayer.java
+++ b/services/core/java/com/android/server/wm/DimLayer.java
@@ -65,6 +65,9 @@
boolean isFullscreen();
/** Returns the display info. of the dim layer user. */
DisplayInfo getDisplayInfo();
+ /** Gets the bounds of the dim layer user. */
+ void getBounds(Rect outBounds);
+ String toShortString();
}
/** The user of this dim layer. */
final DimLayerUser mUser;
@@ -239,8 +242,9 @@
mDuration = duration;
}
}
- if (DEBUG) Slog.v(TAG, "show: mStartAlpha=" + mStartAlpha + " mStartTime=" + mStartTime);
mTargetAlpha = alpha;
+ if (DEBUG) Slog.v(TAG, "show: mStartAlpha=" + mStartAlpha + " mStartTime=" + mStartTime
+ + " mTargetAlpha=" + mTargetAlpha);
}
/** Immediate hide.
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 6b5ecdc..f13f350 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -115,6 +115,8 @@
final DockedStackDividerController mDividerControllerLocked;
+ final DimBehindController mDimBehindController;
+
/**
* @param display May not be null.
* @param service You know.
@@ -128,6 +130,7 @@
mService = service;
initializeDisplayBaseInfo();
mDividerControllerLocked = new DockedStackDividerController(service.mContext, this);
+ mDimBehindController = new DimBehindController(this);
}
int getDisplayId() {
@@ -246,6 +249,7 @@
}
void detachStack(TaskStack stack) {
+ mDimBehindController.removeDimLayerUser(stack);
mStacks.remove(stack);
}
@@ -382,54 +386,23 @@
}
boolean animateDimLayers() {
- boolean result = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
- final Task task = tasks.get(taskNdx);
- result |= task.animateDimLayers();
- if (task.isFullscreen()) {
- // No point in continuing as this task covers the entire screen.
- // Also, fullscreen tasks all share the same dim layer, so we don't want
- // processing of fullscreen task below this one affecting the dim layer state.
- return result;
- }
- }
- }
- return result;
+ return mDimBehindController.animateDimLayers();
}
void resetDimming() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
- tasks.get(taskNdx).clearContinueDimming();
- }
- }
+ mDimBehindController.resetDimming();
}
boolean isDimming() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
- if (tasks.get(taskNdx).isDimming()) {
- return true;
- }
- }
- }
- return false;
+ return mDimBehindController.isDimming();
}
void stopDimmingIfNeeded() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
- tasks.get(taskNdx).stopDimmingIfNeeded();
- }
- }
+ mDimBehindController.stopDimmingIfNeeded();
}
void close() {
+ mDimBehindController.close();
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
mStacks.get(stackNdx).close();
}
@@ -576,6 +549,7 @@
}
}
pw.println();
+ mDimBehindController.dump(prefix + " ", pw);
}
@Override
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1f986dd..af33880 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -29,7 +29,6 @@
import android.util.EventLog;
import android.util.Slog;
import android.util.SparseArray;
-import android.util.TypedValue;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -39,10 +38,6 @@
import java.util.ArrayList;
class Task implements DimLayer.DimLayerUser {
- /** Amount of time in milliseconds to animate the dim surface from one value to another,
- * when no window animation is driving it. */
- private static final int DEFAULT_DIM_DURATION = 200;
-
// Return value from {@link setBounds} indicating no change was made to the Task bounds.
static final int BOUNDS_CHANGE_NONE = 0;
// Return value from {@link setBounds} indicating the position of the Task bounds changed.
@@ -78,17 +73,6 @@
// Whether the task is currently being drag-resized
private boolean mDragResizing;
- // The particular window with FLAG_DIM_BEHIND set. If null, hide mDimLayer.
- WindowStateAnimator mDimWinAnimator;
- // Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}
- private DimLayer mDimLayer;
- // Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the end
- // then stop any dimming.
- private boolean mContinueDimming;
- // Shared dim layer for fullscreen tasks. {@link #mDimLayer} will point to this instead
- // of creating a new object per fullscreen task on a display.
- private static final SparseArray<DimLayer> sSharedFullscreenDimLayers = new SparseArray<>();
-
Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
Configuration config) {
mTaskId = taskId;
@@ -128,6 +112,10 @@
if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask");
mDeferRemoval = false;
+ DisplayContent content = getDisplayContent();
+ if (content != null) {
+ content.mDimBehindController.removeDimLayerUser(this);
+ }
mStack.removeTask(this);
mService.mTaskIdToTask.delete(mTaskId);
}
@@ -228,7 +216,9 @@
mBounds.set(bounds);
mRotation = rotation;
- updateDimLayer();
+ if (displayContent != null) {
+ displayContent.mDimBehindController.updateDimLayer(this);
+ }
mOverrideConfig = mFullscreen ? Configuration.EMPTY : config;
return boundsChange;
}
@@ -261,7 +251,8 @@
}
/** Bounds of the task with other system factors taken into consideration. */
- void getBounds(Rect out) {
+ @Override
+ public void getBounds(Rect out) {
if (useCurrentBounds()) {
// No need to adjust the output bounds if fullscreen or the docked stack is visible
// since it is already what we want to represent to the rest of the system.
@@ -309,139 +300,6 @@
}
}
- /** Updates the dim layer bounds, recreating it if needed. */
- private void updateDimLayer() {
- DimLayer newDimLayer;
- final boolean previousFullscreen =
- mDimLayer != null && sSharedFullscreenDimLayers.indexOfValue(mDimLayer) > -1;
- final int displayId = mStack.getDisplayContent().getDisplayId();
- if (mFullscreen) {
- if (previousFullscreen) {
- // Nothing to do here...
- return;
- }
- // Use shared fullscreen dim layer
- newDimLayer = sSharedFullscreenDimLayers.get(displayId);
- if (newDimLayer == null) {
- if (mDimLayer != null) {
- // Re-purpose the previous dim layer.
- newDimLayer = mDimLayer;
- } else {
- // Create new full screen dim layer.
- newDimLayer = new DimLayer(mService, this, displayId);
- }
- newDimLayer.setBounds(mBounds);
- sSharedFullscreenDimLayers.put(displayId, newDimLayer);
- } else if (mDimLayer != null) {
- mDimLayer.destroySurface();
- }
- } else {
- newDimLayer = (mDimLayer == null || previousFullscreen)
- ? new DimLayer(mService, this, displayId) : mDimLayer;
- newDimLayer.setBounds(mBounds);
- }
- mDimLayer = newDimLayer;
- }
-
- boolean animateDimLayers() {
- final int dimLayer;
- final float dimAmount;
- if (mDimWinAnimator == null) {
- dimLayer = mDimLayer.getLayer();
- dimAmount = 0;
- } else {
- dimLayer = mDimWinAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM;
- dimAmount = mDimWinAnimator.mWin.mAttrs.dimAmount;
- }
- final float targetAlpha = mDimLayer.getTargetAlpha();
- if (targetAlpha != dimAmount) {
- if (mDimWinAnimator == null) {
- mDimLayer.hide(DEFAULT_DIM_DURATION);
- } else {
- long duration = (mDimWinAnimator.mAnimating && mDimWinAnimator.mAnimation != null)
- ? mDimWinAnimator.mAnimation.computeDurationHint()
- : DEFAULT_DIM_DURATION;
- if (targetAlpha > dimAmount) {
- duration = getDimBehindFadeDuration(duration);
- }
- mDimLayer.show(dimLayer, dimAmount, duration);
- }
- } else if (mDimLayer.getLayer() != dimLayer) {
- mDimLayer.setLayer(dimLayer);
- }
- if (mDimLayer.isAnimating()) {
- if (!mService.okToDisplay()) {
- // Jump to the end of the animation.
- mDimLayer.show();
- } else {
- return mDimLayer.stepAnimation();
- }
- }
- return false;
- }
-
- private long getDimBehindFadeDuration(long duration) {
- TypedValue tv = new TypedValue();
- mService.mContext.getResources().getValue(
- com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true);
- if (tv.type == TypedValue.TYPE_FRACTION) {
- duration = (long)tv.getFraction(duration, duration);
- } else if (tv.type >= TypedValue.TYPE_FIRST_INT && tv.type <= TypedValue.TYPE_LAST_INT) {
- duration = tv.data;
- }
- return duration;
- }
-
- void clearContinueDimming() {
- mContinueDimming = false;
- }
-
- void setContinueDimming() {
- mContinueDimming = true;
- }
-
- boolean getContinueDimming() {
- return mContinueDimming;
- }
-
- boolean isDimming() {
- return mDimLayer.isDimming();
- }
-
- boolean isDimming(WindowStateAnimator winAnimator) {
- return mDimWinAnimator == winAnimator && isDimming();
- }
-
- void startDimmingIfNeeded(WindowStateAnimator newWinAnimator) {
- // Only set dim params on the highest dimmed layer.
- // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer.
- if (newWinAnimator.mSurfaceShown && (mDimWinAnimator == null
- || !mDimWinAnimator.mSurfaceShown
- || mDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
- mDimWinAnimator = newWinAnimator;
- if (mDimWinAnimator.mWin.mAppToken == null
- && !mFullscreen && mStack.getDisplayContent() != null) {
- // Dim should cover the entire screen for system windows.
- mStack.getDisplayContent().getLogicalDisplayRect(mTmpRect);
- mDimLayer.setBounds(mTmpRect);
- }
- }
- }
-
- void stopDimmingIfNeeded() {
- if (!mContinueDimming && isDimming()) {
- mDimWinAnimator = null;
- mDimLayer.setBounds(mBounds);
- }
- }
-
- void close() {
- if (mDimLayer != null) {
- mDimLayer.destroySurface();
- mDimLayer = null;
- }
- }
-
void resizeWindows() {
final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
@@ -491,16 +349,14 @@
return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
}
+ @Override
+ public String toShortString() {
+ return "Task=" + mTaskId;
+ }
+
public void printTo(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("taskId="); pw.print(mTaskId);
pw.print(prefix); pw.print("appTokens="); pw.print(mAppTokens);
pw.print(prefix); pw.print("mdr="); pw.println(mDeferRemoval);
- if (mDimLayer.isDimming()) {
- pw.print(prefix); pw.println("mDimLayer:");
- mDimLayer.printTo(prefix + " ", pw);
- pw.print(prefix); pw.print("mDimWinAnimator="); pw.println(mDimWinAnimator);
- } else {
- pw.println();
- }
}
}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 290c2ea..207da47 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -468,6 +468,16 @@
return mTask.mStack.getDisplayInfo();
}
+ @Override
+ public void getBounds(Rect out) {
+ // This dim layer user doesn't need this.
+ }
+
+ @Override
+ public String toShortString() {
+ return TAG;
+ }
+
private int getDragLayerLocked() {
return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
* WindowManagerService.TYPE_LAYER_MULTIPLIER
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index f030b9a..a630993 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -175,6 +175,10 @@
return false;
}
+ if (mDisplayContent != null) {
+ mDisplayContent.mDimBehindController.updateDimLayer(this);
+ }
+
mAnimationBackgroundSurface.setBounds(bounds);
mBounds.set(bounds);
mRotation = rotation;
@@ -201,7 +205,8 @@
}
/** Bounds of the stack with other system factors taken into consideration. */
- void getBounds(Rect out) {
+ @Override
+ public void getBounds(Rect out) {
if (useCurrentBounds()) {
// No need to adjust the output bounds if fullscreen or the docked stack is visible
// since it is already what we want to represent to the rest of the system.
@@ -550,9 +555,6 @@
mAnimationBackgroundSurface.destroySurface();
mAnimationBackgroundSurface = null;
}
- for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
- mTasks.get(taskNdx).close();
- }
mDisplayContent = null;
}
@@ -609,6 +611,11 @@
return "{stackId=" + mStackId + " tasks=" + mTasks + "}";
}
+ @Override
+ public String toShortString() {
+ return "Stack=" + mStackId;
+ }
+
/**
* For docked workspace provides information which side of the screen was the dock anchored.
*/
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 74572cf..c4201d9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -216,6 +216,7 @@
static final boolean DEBUG_STACK = false;
static final boolean DEBUG_DISPLAY = false;
static final boolean DEBUG_POWER = false;
+ static final boolean DEBUG_DIM_LAYER = false;
static final boolean SHOW_SURFACE_ALLOC = false;
static final boolean SHOW_TRANSACTIONS = false;
static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
@@ -8356,8 +8357,10 @@
layerChanged = true;
anyLayerChanged = true;
}
- final Task task = w.getTask();
- if (layerChanged && task != null && task.isDimming(winAnimator)) {
+ final DimLayer.DimLayerUser dimLayerUser = w.getDimLayerUser();
+ final DisplayContent displayContent = w.getDisplayContent();
+ if (layerChanged && dimLayerUser != null && displayContent != null &&
+ displayContent.mDimBehindController.isDimming(dimLayerUser, winAnimator)) {
// Force an animation pass just to update the mDimLayer layer.
scheduleAnimationLocked();
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 55ddbc0..8ace990 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -29,6 +29,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.WindowManagerService.DEBUG_CONFIGURATION;
+import static com.android.server.wm.WindowManagerService.DEBUG_DIM_LAYER;
import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerService.DEBUG_POWER;
@@ -698,10 +699,10 @@
final int height = Math.min(mFrame.height(), mContentFrame.height());
final int width = Math.min(mContentFrame.width(), mFrame.width());
final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
- final int minVisibleHeight =
- mService.dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics);
- final int minVisibleWidth =
- mService.dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics);
+ final int minVisibleHeight = WindowManagerService.dipToPixel(
+ MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics);
+ final int minVisibleWidth = WindowManagerService.dipToPixel(
+ MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics);
final int top = Math.max(mContentFrame.top,
Math.min(mFrame.top, mContentFrame.bottom - minVisibleHeight));
final int left = Math.max(mContentFrame.left + minVisibleWidth - width,
@@ -889,7 +890,7 @@
@Override
public boolean isVoiceInteraction() {
- return mAppToken != null ? mAppToken.voiceInteraction : false;
+ return mAppToken != null && mAppToken.voiceInteraction;
}
boolean setInsetsChanged() {
@@ -934,7 +935,10 @@
return task.mStack;
}
}
- return null;
+ // Some system windows (e.g. "Power off" dialog) don't have a task, but we would still
+ // associate them with some stack to enable dimming.
+ return mAttrs.type >= WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
+ && mDisplayContent != null ? mDisplayContent.getHomeStack() : null;
}
/**
@@ -970,7 +974,8 @@
}
if (forTouch && inFreeformWorkspace()) {
final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
- final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
+ final int delta = WindowManagerService.dipToPixel(
+ RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
bounds.inset(-delta, -delta);
}
}
@@ -1031,8 +1036,7 @@
return false;
}
final AppWindowToken atoken = mAppToken;
- final boolean animating = atoken != null
- ? (atoken.mAppAnimator.animation != null) : false;
+ final boolean animating = atoken != null && atoken.mAppAnimator.animation != null;
return mHasSurface && !mDestroying && !mExiting
&& (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
&& ((!mAttachedHidden && mViewVisibility == View.VISIBLE
@@ -1114,8 +1118,7 @@
* of a transition that has not yet been started.
*/
boolean isReadyForDisplay() {
- if (mRootToken.waitingToShow &&
- mService.mAppTransition.isTransitionSet()) {
+ if (mRootToken.waitingToShow && mService.mAppTransition.isTransitionSet()) {
return false;
}
return mHasSurface && mPolicyVisibility && !mDestroying
@@ -1295,19 +1298,20 @@
}
void handleFlagDimBehind() {
- if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isDisplayedLw() && !mExiting) {
- final Task task = getTask();
- if (task == null) {
- return;
- }
- task.setContinueDimming();
- if (!task.isDimming(mWinAnimator)) {
- if (WindowManagerService.localLOGV) Slog.v(TAG, "Win " + this + " start dimming.");
- task.startDimmingIfNeeded(mWinAnimator);
- }
+ if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && mDisplayContent != null && !mExiting
+ && isDisplayedLw()) {
+ mDisplayContent.mDimBehindController.applyDimBehind(getDimLayerUser(), mWinAnimator);
}
}
+ DimLayer.DimLayerUser getDimLayerUser() {
+ Task task = getTask();
+ if (task != null) {
+ return task;
+ }
+ return getStack();
+ }
+
void maybeRemoveReplacedWindow() {
AppWindowToken token = mAppToken;
if (token != null && token.mReplacingWindow) {
@@ -1512,11 +1516,9 @@
@Override
public boolean isDimming() {
- Task task = getTask();
- if (task == null) {
- return false;
- }
- return task.isDimming(mWinAnimator);
+ final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
+ return dimLayerUser != null && mDisplayContent != null &&
+ mDisplayContent.mDimBehindController.isDimming(dimLayerUser, mWinAnimator);
}
public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 60bf571..ed53501 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1516,12 +1516,7 @@
mDsDy * w.mHScale, mDtDy * w.mVScale);
mAnimator.setPendingLayoutChanges(w.getDisplayId(),
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
- if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) {
- final Task task = w.getTask();
- if (task != null) {
- task.startDimmingIfNeeded(this);
- }
- }
+ w.handleFlagDimBehind();
} catch (RuntimeException e) {
// If something goes wrong with the surface (such
// as running out of memory), don't take down the
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index df0a1c9..db9fcf1 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -642,9 +642,7 @@
handleNotObscuredLocked(w, innerDw, innerDh);
}
- if (task != null && !task.getContinueDimming()) {
- w.handleFlagDimBehind();
- }
+ w.handleFlagDimBehind();
if (isDefaultDisplay && obscuredChanged
&& mWallpaperControllerLocked.isWallpaperTarget(w) && w.isVisibleLw()) {