diff options
10 files changed, 135 insertions, 17 deletions
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig index b71468247e37..985dc102b31b 100644 --- a/core/java/android/window/flags/windowing_frontend.aconfig +++ b/core/java/android/window/flags/windowing_frontend.aconfig @@ -192,4 +192,15 @@ flag { metadata { purpose: PURPOSE_BUGFIX } -}
\ No newline at end of file +} + +flag { + name: "ensure_wallpaper_in_transitions" + namespace: "windowing_frontend" + description: "Ensure that wallpaper window tokens are always present/available for collection in transitions" + bug: "347593088" + metadata { + purpose: PURPOSE_BUGFIX + } +} + diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java index de016d3ae400..5097ed8866c9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java @@ -269,7 +269,9 @@ public class SplitDecorManager extends WindowlessWindowManager { if (update) { if (immediately) { + t.setAlpha(mBackgroundLeash, showVeil ? 1f : 0f); t.setVisibility(mBackgroundLeash, showVeil); + t.setAlpha(mIconLeash, showVeil ? 1f : 0f); t.setVisibility(mIconLeash, showVeil); } else { startFadeAnimation(showVeil, false, null); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java index 5d5bab4e785a..4044e830c3ff 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java @@ -28,13 +28,16 @@ import static android.view.WindowManager.TRANSIT_SLEEP; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.view.WindowManager.fixScale; +import static android.window.TransitionInfo.FLAGS_IS_NON_APP_WINDOW; import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED; import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY; import static android.window.TransitionInfo.FLAG_IS_BEHIND_STARTING_WINDOW; import static android.window.TransitionInfo.FLAG_IS_OCCLUDED; +import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; import static android.window.TransitionInfo.FLAG_NO_ANIMATION; import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT; +import static com.android.window.flags.Flags.ensureWallpaperInTransitions; import static com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary; import static com.android.wm.shell.shared.TransitionUtil.isClosingType; import static com.android.wm.shell.shared.TransitionUtil.isOpeningType; @@ -74,6 +77,7 @@ import androidx.annotation.BinderThread; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; +import com.android.window.flags.Flags; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; @@ -513,12 +517,17 @@ public class Transitions implements RemoteCallable<Transitions>, boolean isOpening = isOpeningType(info.getType()); for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); - if (change.hasFlags(TransitionInfo.FLAGS_IS_NON_APP_WINDOW)) { + if (change.hasFlags(FLAGS_IS_NON_APP_WINDOW & ~FLAG_IS_WALLPAPER)) { // Currently system windows are controlled by WindowState, so don't change their // surfaces. Otherwise their surfaces could be hidden or cropped unexpectedly. - // This includes Wallpaper (always z-ordered at bottom) and IME (associated with - // app), because there may not be a transition associated with their visibility - // changes, and currently they don't need transition animation. + // This includes IME (associated with app), because there may not be a transition + // associated with their visibility changes, and currently they don't need a + // transition animation. + continue; + } + if (change.hasFlags(FLAG_IS_WALLPAPER) && !ensureWallpaperInTransitions()) { + // Wallpaper is always z-ordered at bottom, and historically is not animated by + // transition handlers. continue; } final SurfaceControl leash = change.getLeash(); @@ -571,6 +580,14 @@ public class Transitions implements RemoteCallable<Transitions>, final boolean isOpening = isOpeningType(transitType); final boolean isClosing = isClosingType(transitType); final int mode = change.getMode(); + // Ensure wallpapers stay in the back + if (change.hasFlags(FLAG_IS_WALLPAPER) && Flags.ensureWallpaperInTransitions()) { + if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) { + return -zSplitLine + numChanges - i; + } else { + return -zSplitLine - i; + } + } // Put all the OPEN/SHOW on top if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) { if (isOpening) { diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 1cbf67ee0d0e..bfc36b84991a 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -1105,3 +1105,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "translucent_occluding_activity_fix" + namespace: "systemui" + description: "Fixes occlusion animation for transluent activities" + bug: "303010980" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt index b6e4e9b13a1c..c14ee6208176 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt @@ -22,6 +22,7 @@ import android.app.PendingIntent import android.app.TaskInfo import android.app.WindowConfiguration import android.content.ComponentName +import android.graphics.Color import android.graphics.Matrix import android.graphics.Rect import android.graphics.RectF @@ -53,6 +54,7 @@ import com.android.app.animation.Interpolators import com.android.internal.annotations.VisibleForTesting import com.android.internal.policy.ScreenDecorationsUtils import com.android.systemui.Flags.activityTransitionUseLargestWindow +import com.android.systemui.Flags.translucentOccludingActivityFix import com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary import com.android.wm.shell.shared.IShellTransitions import com.android.wm.shell.shared.ShellTransitions @@ -991,7 +993,12 @@ constructor( controller.createAnimatorState() } val windowBackgroundColor = - window.taskInfo?.let { callback.getBackgroundColor(it) } ?: window.backgroundColor + if (translucentOccludingActivityFix() && window.isTranslucent) { + Color.TRANSPARENT + } else { + window.taskInfo?.let { callback.getBackgroundColor(it) } + ?: window.backgroundColor + } // TODO(b/184121838): We should somehow get the top and bottom radius of the window // instead of recomputing isExpandingFullyAbove here. diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 2d60fcca58cc..ed8d4263b212 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -42,6 +42,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.Flags.notifyPowerManagerUserActivityBackground; import static com.android.systemui.Flags.refactorGetCurrentUser; +import static com.android.systemui.Flags.translucentOccludingActivityFix; import static com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel.DREAMING_ANIMATION_DURATION_MS; import android.animation.Animator; @@ -1035,6 +1036,17 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, (int) (fullWidth - initialWidth) /* left */, fullWidth /* right */, mWindowCornerRadius, mWindowCornerRadius); + } else if (translucentOccludingActivityFix() + && mOccludingRemoteAnimationTarget != null + && mOccludingRemoteAnimationTarget.isTranslucent) { + // Animating in a transparent window looks really weird. Just let it be + // fullscreen and the app can do an internal animation if it wants to. + return new TransitionAnimator.State( + 0, + fullHeight, + 0, + fullWidth, + 0f, 0f); } else { final float initialHeight = fullHeight / 2f; final float initialWidth = fullWidth / 2f; @@ -1398,6 +1410,11 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, private final Lazy<DreamViewModel> mDreamViewModel; private final Lazy<CommunalTransitionViewModel> mCommunalTransitionViewModel; private RemoteAnimationTarget mRemoteAnimationTarget; + + /** + * The most recent RemoteAnimationTarget provided for an occluding activity animation. + */ + private RemoteAnimationTarget mOccludingRemoteAnimationTarget; private boolean mShowCommunalWhenUnoccluding = false; private final Lazy<WindowManagerLockscreenVisibilityManager> mWmLockscreenVisibilityManager; @@ -3930,6 +3947,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, public void onAnimationStart(int transit, RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException { + // Save mRemoteAnimationTarget for reference in the animation controller. Needs to be + // called prior to super.onAnimationStart() since that's the call that eventually asks + // the animation controller to configure the animation state. + if (apps.length > 0) { + mOccludingRemoteAnimationTarget = apps[0]; + } + super.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback); mInteractionJankMonitor.begin( diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 04ee4acd44c2..dcfe350b1c42 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -1694,7 +1694,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { // ActivityRecord#canShowWindows() may reject to show its window. The visibility also // needs to be updated for STATE_ABORT. commitVisibleActivities(transaction); - commitVisibleWallpapers(); + commitVisibleWallpapers(transaction); if (mTransactionCompletedListeners != null) { for (int i = 0; i < mTransactionCompletedListeners.size(); i++) { @@ -2125,7 +2125,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { /** * Reset waitingToshow for all wallpapers, and commit the visibility of the visible ones */ - private void commitVisibleWallpapers() { + private void commitVisibleWallpapers(SurfaceControl.Transaction t) { boolean showWallpaper = shouldWallpaperBeVisible(); for (int i = mParticipants.size() - 1; i >= 0; --i) { final WallpaperWindowToken wallpaper = mParticipants.valueAt(i).asWallpaperToken(); @@ -2133,6 +2133,14 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { if (!wallpaper.isVisible() && wallpaper.isVisibleRequested()) { wallpaper.commitVisibility(showWallpaper); } + if (showWallpaper && Flags.ensureWallpaperInTransitions() + && wallpaper.isVisibleRequested() + && getLeashSurface(wallpaper, t) != wallpaper.getSurfaceControl()) { + // If on a rotation leash, we need to explicitly show the wallpaper surface + // because shell only gets the leash and we don't allow non-transition logic + // to touch the surfaces until the transition is over. + t.show(wallpaper.getSurfaceControl()); + } } } } @@ -2545,9 +2553,9 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { if (wc.asWindowState() != null) continue; final ChangeInfo changeInfo = changes.get(wc); - - // Reject no-ops - if (!changeInfo.hasChanged()) { + // Reject no-ops, unless wallpaper + if (!changeInfo.hasChanged() + && (!Flags.ensureWallpaperInTransitions() || wc.asWallpaperToken() == null)) { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " Rejecting as no-op: %s", wc); continue; @@ -2831,6 +2839,13 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { // Use parent rotation because shell doesn't know the surface is rotated. endRotation = parent.getWindowConfiguration().getRotation(); } + } else if (isWallpaper(target) && Flags.ensureWallpaperInTransitions() + && target.getRelativeDisplayRotation() != 0 + && !target.mTransitionController.useShellTransitionsRotation()) { + // If the wallpaper is "fixed-rotated", shell is unaware of this, so use the + // "as-if-not-rotating" bounds and rotation + change.setEndAbsBounds(parent.getBounds()); + endRotation = parent.getWindowConfiguration().getRotation(); } else { change.setEndAbsBounds(bounds); } diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 3e43f5a2da66..86440ac3782d 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -60,6 +60,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ToBooleanFunction; import com.android.server.wallpaper.WallpaperCropper.WallpaperCropUtils; +import com.android.window.flags.Flags; import java.io.PrintWriter; import java.util.ArrayList; @@ -764,10 +765,19 @@ class WallpaperController { void collectTopWallpapers(Transition transition) { if (mFindResults.hasTopShowWhenLockedWallpaper()) { - transition.collect(mFindResults.mTopWallpaper.mTopShowWhenLockedWallpaper); + if (Flags.ensureWallpaperInTransitions()) { + transition.collect(mFindResults.mTopWallpaper.mTopShowWhenLockedWallpaper.mToken); + } else { + transition.collect(mFindResults.mTopWallpaper.mTopShowWhenLockedWallpaper); + } + } if (mFindResults.hasTopHideWhenLockedWallpaper()) { - transition.collect(mFindResults.mTopWallpaper.mTopHideWhenLockedWallpaper); + if (Flags.ensureWallpaperInTransitions()) { + transition.collect(mFindResults.mTopWallpaper.mTopHideWhenLockedWallpaper.mToken); + } else { + transition.collect(mFindResults.mTopWallpaper.mTopHideWhenLockedWallpaper); + } } } diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java index 9d1551c12216..b7f8505b4a65 100644 --- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java +++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java @@ -32,6 +32,7 @@ import android.os.RemoteException; import android.util.SparseArray; import com.android.internal.protolog.common.ProtoLog; +import com.android.window.flags.Flags; import java.util.function.Consumer; @@ -80,6 +81,20 @@ class WallpaperWindowToken extends WindowToken { mDisplayContent.mWallpaperController.removeWallpaperToken(this); } + @Override + public void prepareSurfaces() { + super.prepareSurfaces(); + + if (Flags.ensureWallpaperInTransitions()) { + // Similar to Task.prepareSurfaces, outside of transitions we need to apply visibility + // changes directly. In transitions the transition player will take care of applying the + // visibility change. + if (!mTransitionController.inTransition(this)) { + getSyncTransaction().setVisibility(mSurfaceControl, isVisible()); + } + } + } + /** * Controls whether this wallpaper shows underneath the keyguard or is hidden and only * revealed once keyguard is dismissed. diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 6fd7aa0e4a78..9ecd49213237 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -63,6 +63,7 @@ import android.view.animation.AnimationUtils; import com.android.internal.protolog.common.LogLevel; import com.android.internal.protolog.common.ProtoLog; +import com.android.window.flags.Flags; import com.android.server.policy.WindowManagerPolicy; import java.io.PrintWriter; @@ -374,9 +375,13 @@ class WindowStateAnimator { ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY: %s. %s", mWin, new RuntimeException().fillInStackTrace()); destroySurface(t); - // Don't hide wallpaper if we're deferring the surface destroy - // because of a surface change. - mWallpaperControllerLocked.hideWallpapers(mWin); + if (Flags.ensureWallpaperInTransitions()) { + if (mWallpaperControllerLocked.isWallpaperTarget(mWin)) { + mWin.requestUpdateWallpaperIfNeeded(); + } + } else { + mWallpaperControllerLocked.hideWallpapers(mWin); + } } catch (RuntimeException e) { Slog.w(TAG, "Exception thrown when destroying Window " + this + " surface " + mSurfaceController + " session " + mSession + ": " @@ -431,7 +436,9 @@ class WindowStateAnimator { if (!w.isOnScreen()) { hide(t, "prepareSurfaceLocked"); - mWallpaperControllerLocked.hideWallpapers(w); + if (!w.mIsWallpaper || !Flags.ensureWallpaperInTransitions()) { + mWallpaperControllerLocked.hideWallpapers(w); + } // If we are waiting for this window to handle an orientation change. If this window is // really hidden (gone for layout), there is no point in still waiting for it. |