Use and reparent the task's dim
Instead of using the display area's dimmer, each window has access only
to it's own task's dimmer. The associated dim layer can be reparented to
the display area when needed.
Bug: 352522056
Test: DimmerTests
Flag: com.android.window.flags.use_tasks_dim_only
Change-Id: I4723efbd6bd8fc3a6613970b244b1e69996a472a
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index 7f48c42..76989f9 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -180,6 +180,17 @@
}
flag {
+ name: "use_tasks_dim_only"
+ namespace: "windowing_frontend"
+ description: "Only use the task's dim and reparent it to the display area when needed instead of coordinating multiple dimmers"
+ bug: "352522056"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "release_snapshot_aggressively"
namespace: "windowing_frontend"
description: "Actively release task snapshot memory"
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 7c31177..2d1eb41 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -28,7 +28,13 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.ProtoLog;
+import com.android.window.flags.Flags;
+
+/**
+ * Utility class for use by a WindowContainer implementation to add "DimLayer" support, that is
+ * black layers of varying opacity at various Z-levels which create the effect of a Dim.
+ */
class Dimmer {
/**
@@ -122,8 +128,10 @@
/**
* Set the parameters to prepare the dim to be relative parented to the dimming container
*/
- void prepareReparent(@NonNull WindowContainer<?> relativeParent, int relativeLayer) {
+ void prepareReparent(@NonNull WindowContainer<?> geometryParent,
+ @NonNull WindowContainer<?> relativeParent, int relativeLayer) {
mAnimationHelper.setRequestedRelativeParent(relativeParent, relativeLayer);
+ mAnimationHelper.setRequestedGeometryParent(geometryParent);
}
/**
@@ -138,7 +146,8 @@
* Whether anyone is currently requesting the dim
*/
boolean isDimming() {
- return mLastRequestedDimContainer != null;
+ return mLastRequestedDimContainer != null
+ && (mHostContainer.isVisibleRequested() || !Flags.useTasksDimOnly());
}
private SurfaceControl makeDimLayer() {
@@ -208,13 +217,15 @@
* the child of the host should call adjustRelativeLayer and {@link Dimmer#adjustAppearance} to
* continue dimming. Indeed, this method won't be able to keep dimming or get a new DimState
* without also adjusting the appearance.
+ * @param geometryParent The container that defines the geometry of the dim
* @param dimmingContainer The container which to dim above. Should be a child of the host.
* @param relativeLayer The position of the dim wrt the container
*/
- public void adjustRelativeLayer(@NonNull WindowContainer<?> dimmingContainer,
+ public void adjustPosition(@NonNull WindowContainer<?> geometryParent,
+ @NonNull WindowContainer<?> dimmingContainer,
int relativeLayer) {
if (mDimState != null) {
- mDimState.prepareReparent(dimmingContainer, relativeLayer);
+ mDimState.prepareReparent(geometryParent, dimmingContainer, relativeLayer);
}
}
@@ -236,7 +247,9 @@
return false;
} else {
// Someone is dimming, show the requested changes
- mDimState.adjustSurfaceLayout(t);
+ if (!Flags.useTasksDimOnly()) {
+ mDimState.adjustSurfaceLayout(t);
+ }
final WindowState ws = mDimState.mLastRequestedDimContainer.asWindowState();
if (!mDimState.mIsVisible && ws != null && ws.mActivityRecord != null
&& ws.mActivityRecord.mStartingData != null) {
@@ -263,6 +276,7 @@
return mDimState != null ? mDimState.mDimSurface : null;
}
+ @Deprecated
Rect getDimBounds() {
return mDimState != null ? mDimState.mDimBounds : null;
}
diff --git a/services/core/java/com/android/server/wm/DimmerAnimationHelper.java b/services/core/java/com/android/server/wm/DimmerAnimationHelper.java
index df1549e..3dba57f 100644
--- a/services/core/java/com/android/server/wm/DimmerAnimationHelper.java
+++ b/services/core/java/com/android/server/wm/DimmerAnimationHelper.java
@@ -26,6 +26,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
@@ -48,6 +49,7 @@
private float mAlpha = -1f;
private int mBlurRadius = -1;
private WindowContainer<?> mDimmingContainer = null;
+ private WindowContainer<?> mGeometryParent = null;
private int mRelativeLayer = -1;
private static final float EPSILON = 0.0001f;
@@ -103,6 +105,11 @@
mRequestedProperties.mRelativeLayer = relativeLayer;
}
+ // Sets the requested layer to reparent the dim to without applying it immediately
+ void setRequestedGeometryParent(WindowContainer<?> geometryParent) {
+ mRequestedProperties.mGeometryParent = geometryParent;
+ }
+
// Sets a requested change without applying it immediately
void setRequestedAppearance(float alpha, int blurRadius) {
mRequestedProperties.mAlpha = alpha;
@@ -129,7 +136,9 @@
}
dim.ensureVisible(t);
- relativeReparent(dim.mDimSurface,
+ reparent(dim.mDimSurface,
+ mRequestedProperties.mGeometryParent != mCurrentProperties.mGeometryParent
+ ? mRequestedProperties.mGeometryParent.getSurfaceControl() : null,
mRequestedProperties.mDimmingContainer.getSurfaceControl(),
mRequestedProperties.mRelativeLayer, t);
@@ -214,11 +223,17 @@
}
/**
- * Change the relative parent of this dim layer
+ * Change the geometry and relative parent of this dim layer
*/
- void relativeReparent(@NonNull SurfaceControl dimLayer, @NonNull SurfaceControl relativeParent,
- int relativePosition, @NonNull SurfaceControl.Transaction t) {
+ void reparent(@NonNull SurfaceControl dimLayer,
+ @Nullable SurfaceControl newGeometryParent,
+ @NonNull SurfaceControl relativeParent,
+ int relativePosition,
+ @NonNull SurfaceControl.Transaction t) {
try {
+ if (newGeometryParent != null) {
+ t.reparent(dimLayer, newGeometryParent);
+ }
t.setRelativeLayer(dimLayer, relativeParent, relativePosition);
} catch (NullPointerException e) {
Log.w(TAG, "Tried to change parent of dim " + dimLayer + " after remove", e);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 259ca83..74adeb9 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3201,6 +3201,14 @@
return "Task=" + mTaskId;
}
+ WindowContainer<?> getDimmerParent() {
+ if (!inMultiWindowMode() && isTranslucentForTransition()) {
+ return getRootDisplayArea();
+ }
+ return this;
+ }
+
+ @Deprecated
@Override
Dimmer getDimmer() {
// If the window is in multi-window mode, we want to dim at the Task level to ensure the dim
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index e07b54b..62e2454 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -3105,6 +3105,7 @@
return forAllWindows(getDimBehindWindow, true);
}
+ @Deprecated
@Override
Dimmer getDimmer() {
// If this is in an embedded TaskFragment and we want the dim applies on the TaskFragment.
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index cf5a1e6..358adc3 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -463,14 +463,26 @@
boolean canApplyDim(@NonNull Task task) {
if (mTransientLaunches == null) return true;
- final Dimmer dimmer = task.getDimmer();
- if (dimmer == null) {
- return false;
- }
- if (dimmer.hostIsTask()) {
+ if (Flags.useTasksDimOnly()) {
+ WindowContainer<?> dimmerParent = task.getDimmerParent();
+ if (dimmerParent == null) {
+ return false;
+ }
// Always allow to dim if the host only affects its task.
- return true;
+ if (dimmerParent.asTask() == task) {
+ return true;
+ }
+ } else {
+ final Dimmer dimmer = task.getDimmer();
+ if (dimmer == null) {
+ return false;
+ }
+ if (dimmer.hostIsTask()) {
+ // Always allow to dim if the host only affects its task.
+ return true;
+ }
}
+
// The dimmer host of a translucent task can be a display, then it is not in transient-hide.
for (int i = mTransientLaunches.size() - 1; i >= 0; --i) {
// The transient task is usually the task of recents/home activity.
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index eb1a80b..64f9c01 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -107,11 +107,10 @@
import android.window.IWindowContainerToken;
import android.window.WindowContainerToken;
-import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
-import com.android.internal.protolog.common.LogLevel;
import com.android.internal.protolog.ProtoLog;
+import com.android.internal.protolog.common.LogLevel;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.wm.SurfaceAnimator.Animatable;
import com.android.server.wm.SurfaceAnimator.AnimationType;
@@ -3765,6 +3764,7 @@
}, true /* traverseTopToBottom */);
}
+ @Deprecated
Dimmer getDimmer() {
if (mParent == null) {
return null;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2860532..2bcbbc0 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -103,6 +103,7 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ANIM;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_DIMMER;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
@@ -5195,9 +5196,10 @@
}
private void applyDims() {
+ Task task = getTask();
if (((mAttrs.flags & FLAG_DIM_BEHIND) != 0 || shouldDrawBlurBehind())
&& mWinAnimator.getShown()
- && !mHidden && mTransitionController.canApplyDim(getTask())) {
+ && !mHidden && mTransitionController.canApplyDim(task)) {
// Only show the Dimmer when the following is satisfied:
// 1. The window has the flag FLAG_DIM_BEHIND or blur behind is requested
// 2. The WindowToken is not hidden so dims aren't shown when the window is exiting.
@@ -5210,10 +5212,31 @@
// If the window is visible from surface flinger perspective (mWinAnimator.getShown())
// but not window manager visible (!isVisibleNow()), it can still be the parent of the
// dim, but can not create a new surface or continue a dim alone.
- if (isVisibleNow()) {
- getDimmer().adjustAppearance(this, dimAmount, blurRadius);
+ Dimmer dimmer;
+ WindowContainer<?> geometryParent = task;
+ if (Flags.useTasksDimOnly()) {
+ if (task != null) {
+ geometryParent = task.getDimmerParent();
+ dimmer = task.mDimmer;
+ } else {
+ RootDisplayArea displayArea = getRootDisplayArea();
+ geometryParent = displayArea;
+ dimmer = displayArea != null ? displayArea.getDimmer() : null;
+ }
+ if (dimmer == null) {
+ ProtoLog.e(WM_DEBUG_DIMMER, "WindowState %s does not have task or"
+ + " display area for dimming", this);
+ return;
+ }
+ } else {
+ dimmer = getDimmer();
}
- getDimmer().adjustRelativeLayer(this, -1 /* relativeLayer */);
+
+ if (isVisibleNow()) {
+ dimmer.adjustAppearance(this, dimAmount, blurRadius);
+ }
+ dimmer.adjustPosition(geometryParent,
+ this /* relativeParent */, -1 /* relativeLayer */);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
index 08f1dff..771e290 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
@@ -32,11 +32,13 @@
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsDisabled;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import com.android.server.testutils.StubTransaction;
import com.android.server.wm.utils.MockAnimationAdapter;
+import com.android.window.flags.Flags;
import org.junit.Before;
import org.junit.Test;
@@ -142,11 +144,12 @@
}
@Test
+ @RequiresFlagsDisabled(Flags.FLAG_USE_TASKS_DIM_ONLY)
public void testUpdateDimsAppliesCrop() {
mHost.addChild(mChild, 0);
mDimmer.adjustAppearance(mChild, 1, 1);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
int width = 100;
int height = 300;
@@ -163,7 +166,7 @@
final int blur = 50;
mHost.addChild(mChild, 0);
mDimmer.adjustAppearance(mChild, alpha, blur);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
SurfaceControl dimLayer = mDimmer.getDimLayer();
assertNotNull("Dimmer should have created a surface", dimLayer);
@@ -184,12 +187,12 @@
final int blur = 50;
// Dim once
mDimmer.adjustAppearance(mChild, alpha, blur);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
SurfaceControl dimLayer = mDimmer.getDimLayer();
mDimmer.updateDims(mTransaction);
// Reset, and don't dim
mDimmer.resetDimStates();
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
mDimmer.updateDims(mTransaction);
verify(mTransaction).show(dimLayer);
verify(mTransaction).remove(dimLayer);
@@ -203,24 +206,25 @@
final int blur = 20;
// Dim once
mDimmer.adjustAppearance(mChild, alpha, blur);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
SurfaceControl dimLayer = mDimmer.getDimLayer();
mDimmer.updateDims(mTransaction);
// Reset and dim again
mDimmer.resetDimStates();
mDimmer.adjustAppearance(mChild, alpha, blur);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
mDimmer.updateDims(mTransaction);
verify(mTransaction).show(dimLayer);
verify(mTransaction, never()).remove(dimLayer);
}
@Test
+ @RequiresFlagsDisabled(Flags.FLAG_USE_TASKS_DIM_ONLY)
public void testDimUpdateWhileDimming() {
mHost.addChild(mChild, 0);
final float alpha = 0.8f;
mDimmer.adjustAppearance(mChild, alpha, 20);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
final Rect bounds = mDimmer.getDimBounds();
SurfaceControl dimLayer = mDimmer.getDimLayer();
@@ -240,7 +244,7 @@
public void testRemoveDimImmediately() {
mHost.addChild(mChild, 0);
mDimmer.adjustAppearance(mChild, 1, 2);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
SurfaceControl dimLayer = mDimmer.getDimLayer();
mDimmer.updateDims(mTransaction);
verify(mTransaction, times(1)).show(dimLayer);
@@ -265,18 +269,18 @@
mDimmer.resetDimStates();
mDimmer.adjustAppearance(mChild, 0.1f, 0);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
SurfaceControl dimLayer = mDimmer.getDimLayer();
mDimmer.updateDims(mTransaction);
mDimmer.resetDimStates();
mDimmer.adjustAppearance(mChild, 0.2f, 0);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
mDimmer.updateDims(mTransaction);
mDimmer.resetDimStates();
mDimmer.adjustAppearance(mChild, 0.3f, 0);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
mDimmer.updateDims(mTransaction);
verify(mTransaction).setAlpha(dimLayer, 0.2f);
@@ -296,18 +300,18 @@
mDimmer.resetDimStates();
mDimmer.adjustAppearance(mChild, 0.2f, 0);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
SurfaceControl dimLayer = mDimmer.getDimLayer();
mDimmer.updateDims(mTransaction);
mDimmer.resetDimStates();
mDimmer.adjustAppearance(mChild, 0.1f, 0);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
mDimmer.updateDims(mTransaction);
mDimmer.resetDimStates();
mDimmer.adjustAppearance(mChild, 0f, 0);
- mDimmer.adjustRelativeLayer(mChild, -1);
+ mDimmer.adjustPosition(mChild, mChild, -1);
mDimmer.updateDims(mTransaction);
mDimmer.resetDimStates();
@@ -326,13 +330,13 @@
mHost.addChild(second, 1);
mDimmer.adjustAppearance(first, 0.5f, 0);
- mDimmer.adjustRelativeLayer(first, -1);
+ mDimmer.adjustPosition(mChild, first, -1);
SurfaceControl dimLayer = mDimmer.getDimLayer();
mDimmer.updateDims(mTransaction);
mDimmer.resetDimStates();
mDimmer.adjustAppearance(second, 0.9f, 0);
- mDimmer.adjustRelativeLayer(second, -1);
+ mDimmer.adjustPosition(mChild, second, -1);
mDimmer.updateDims(mTransaction);
verify(sTestAnimation, times(2)).startAnimation(
@@ -354,10 +358,10 @@
mHost.addChild(second, 1);
mDimmer.adjustAppearance(first, 0.5f, 0);
- mDimmer.adjustRelativeLayer(first, -1);
+ mDimmer.adjustPosition(mChild, first, -1);
SurfaceControl dimLayer = mDimmer.getDimLayer();
mDimmer.adjustAppearance(second, 0.9f, 0);
- mDimmer.adjustRelativeLayer(second, -1);
+ mDimmer.adjustPosition(mChild, second, -1);
mDimmer.updateDims(mTransaction);
verify(sTestAnimation, times(1)).startAnimation(