summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Riddle Hsu <riddlehsu@google.com> 2023-06-14 22:02:43 +0800
committer Riddle Hsu <riddlehsu@google.com> 2023-06-14 18:08:53 +0000
commite0ef87d884cd04a50efbd056d67a796b1f3aea4a (patch)
treeea9783874a8705dcea815e1c080904d638489bbb
parentf80ef9353004370127736a674f5cf1b76cf4fd55 (diff)
Toggle dim according to progress of recents animation
The major problem when running recents animation: - Initial: canAffectSystemUiFlags=false by setTransientLaunch - Drag the app task a bit: canAffectSystemUiFlags=true by setRecentsAppBehindSystemBars - Drag the app task to original position to exit recents animation: canAffectSystemUiFlags=false by setRecentsAppBehindSystemBars If canAffectSystemUiFlags is not true (default), DisplayArea#prepareSurface will try to cancel dim. But if there is a valid window to request dim, it will cause endless animation loop between applyDim and resetDimStates and the dim is never visible. The state can be corrected by resetting canAffectSystemUiFlags to true when the transient(recents) transition is finished. Also instead of searching canAffectSystemUiFlags on every prepareSurface, it is more efficient to only check if a dimmer can request to show according the status of a playing recents transition. This would also fix ugly animation when swiping a translucent task to home that the dimmer covers home during entire animation. Also see: Reset dim in legacy: I6e275b778da4cb7aeda3b3483a14f5f9d2796e44 Set flag with shell: I552eea738aed5566eb897bb9c68507e83ac43e1d Fix: 286955271 Test: atest TransitionTests#testTransientLaunch Change-Id: I5843abb925eb2466be34e1dcb96d4cfd83e4dc8a
-rw-r--r--services/core/java/com/android/server/wm/Dimmer.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayArea.java3
-rw-r--r--services/core/java/com/android/server/wm/Transition.java32
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java13
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TransitionTests.java5
6 files changed, 58 insertions, 2 deletions
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 8660becf56a9..89f044bdd163 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -178,6 +178,10 @@ class Dimmer {
mSurfaceAnimatorStarter = surfaceAnimatorStarter;
}
+ WindowContainer<?> getHost() {
+ return mHost;
+ }
+
private SurfaceControl makeDimLayer() {
return mHost.makeChildSurface(null)
.setParent(mHost.getSurfaceControl())
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index 9f59f5a30caf..f81e5d453434 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -790,7 +790,8 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
// If SystemUI is dragging for recents, we want to reset the dim state so any dim layer
// on the display level fades out.
- if (forAllTasks(task -> !task.canAffectSystemUiFlags())) {
+ if (!mTransitionController.isShellTransitionsEnabled()
+ && forAllTasks(task -> !task.canAffectSystemUiFlags())) {
mDimmer.resetDimStates();
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index aad12251502d..3d9edcac8eb1 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -397,6 +397,28 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
return false;
}
+ boolean canApplyDim(@NonNull Task task) {
+ if (mTransientLaunches == null) return true;
+ final Dimmer dimmer = task.getDimmer();
+ final WindowContainer<?> dimmerHost = dimmer != null ? dimmer.getHost() : null;
+ if (dimmerHost == null) return false;
+ if (isInTransientHide(dimmerHost)) {
+ // The layer of dimmer is inside transient-hide task, then allow to dim.
+ 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.
+ final Task transientTask = mTransientLaunches.keyAt(i).getTask();
+ if (transientTask != null && transientTask.canAffectSystemUiFlags()) {
+ // It usually means that the recents animation has moved the transient-hide task
+ // an noticeable distance, then the display level dimmer should not show.
+ return false;
+ }
+ }
+ return true;
+ }
+
boolean hasTransientLaunch() {
return mTransientLaunches != null && !mTransientLaunches.isEmpty();
}
@@ -1224,6 +1246,16 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
mController.mAtm.mRootWindowContainer.getDisplayContent(mRecentsDisplayId);
dc.getInputMonitor().setActiveRecents(null /* activity */, null /* layer */);
}
+ if (mTransientLaunches != null) {
+ for (int i = mTransientLaunches.size() - 1; i >= 0; --i) {
+ // Reset the ability of controlling SystemUi which might be changed by
+ // setTransientLaunch or setRecentsAppBehindSystemBars.
+ final Task task = mTransientLaunches.keyAt(i).getTask();
+ if (task != null) {
+ task.setCanAffectSystemUiFlags(true);
+ }
+ }
+ }
for (int i = 0; i < mTargetDisplays.size(); ++i) {
final DisplayContent dc = mTargetDisplays.get(i);
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 359b353ba336..436bb255198b 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -476,6 +476,19 @@ class TransitionController {
return false;
}
+ boolean canApplyDim(@Nullable Task task) {
+ if (task == null) {
+ // Always allow non-activity window.
+ return true;
+ }
+ for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
+ if (!mPlayingTransitions.get(i).canApplyDim(task)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* During transient-launch, the "behind" app should retain focus during the transition unless
* something takes focus from it explicitly (eg. by calling ATMS.setFocusedTask or by another
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8f49384f6101..60d9d7ddbabe 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5121,12 +5121,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private void applyDims() {
if (((mAttrs.flags & FLAG_DIM_BEHIND) != 0 || shouldDrawBlurBehind())
- && isVisibleNow() && !mHidden) {
+ && isVisibleNow() && !mHidden && mTransitionController.canApplyDim(getTask())) {
// 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.
// 3. The WS is considered visible according to the isVisible() method
// 4. The WS is not hidden.
+ // 5. The window is not in a transition or is in a transition that allows to dim.
mIsDimming = true;
final float dimAmount = (mAttrs.flags & FLAG_DIM_BEHIND) != 0 ? mAttrs.dimAmount : 0;
final int blurRadius = shouldDrawBlurBehind() ? mAttrs.getBlurBehindRadius() : 0;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 11267268a6fa..df3629bf16c9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1452,6 +1452,11 @@ public class TransitionTests extends WindowTestsBase {
}
});
assertTrue(activity1.isVisible());
+ doReturn(false).when(task1).isTranslucent(null);
+ assertTrue(controller.canApplyDim(task1));
+ doReturn(true).when(task1).isTranslucent(null);
+ assertFalse(controller.canApplyDim(task1));
+
controller.finishTransition(closeTransition);
assertTrue(wasInFinishingTransition[0]);
assertNull(controller.mFinishingTransition);