diff options
| author | 2021-02-17 13:07:15 -0800 | |
|---|---|---|
| committer | 2021-03-03 12:33:25 -0800 | |
| commit | a841c1545934632c4eee8a0eeb52eb4908b8f4de (patch) | |
| tree | e4ea78af3661b1a4da3561bf35c0d92acd5747c5 | |
| parent | 1c2df9c56243e354d85a7d8c2e0a59edfde94b57 (diff) | |
Use clientVisibility and visibleRequested model for wallpaper
This is to maintain similarity to ActivityRecord. ClientVisiblility
is now moved up to WindowToken and shared. VisibleRequested is still
separated since other windowtokens don't support it.
This lets us replace wallpaper-specific logic like deferHideWallpaper
in favor of the same visibility model as activity.
This model is effectively:
X calls setVisibility(v)
sets visibleRequested = v
if there's a transition, only commit the visibility when appearing.
othrewise, commit here.
If there was an ongoing transition, once the transition is over,
call commitVisibility.
Bug: 180143925
Test: Everything should behave the same and existing test should pass
atest WallpaperControllerTests
Change-Id: I7bd216922983c6bca5a3b39e5a09c55889f788ee
15 files changed, 254 insertions, 172 deletions
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index cabfad44cfb9..6d3810bf45bd 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -43,6 +43,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "-2093859262": { + "message": "setClientVisible: %s clientVisible=%b Callers=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowToken.java" + }, "-2072089308": { "message": "Attempted to add window with token that is a sub-window: %s. Aborting.", "level": "WARN", @@ -823,12 +829,6 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java" }, - "-1144293044": { - "message": "SURFACE SET FREEZE LAYER: %s", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" - }, "-1142279614": { "message": "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s", "level": "VERBOSE", @@ -1831,6 +1831,12 @@ "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, + "63329306": { + "message": "commitVisibility: %s: visible=%b mVisibleRequested=%b", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/WallpaperWindowToken.java" + }, "73987756": { "message": "ControlAdapter onAnimationCancelled mSource: %s mControlTarget: %s", "level": "INFO", @@ -2461,6 +2467,12 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, + "691515534": { + "message": " Commit wallpaper becoming invisible: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" + }, "693423992": { "message": "setAnimationLocked: setting mFocusMayChange true", "level": "INFO", diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 593238899e54..0ea2c3363de6 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -580,9 +580,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private Task mLastParent; - // Have we told the window clients to show themselves? - private boolean mClientVisible; - boolean firstWindowDrawn; /** Whether the visible window(s) of this activity is drawn. */ private boolean mReportedDrawn; @@ -998,7 +995,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pw.print(prefix); pw.print("mOrientation="); pw.println(ActivityInfo.screenOrientationToString(mOrientation)); pw.println(prefix + "mVisibleRequested=" + mVisibleRequested - + " mVisible=" + mVisible + " mClientVisible=" + mClientVisible + + " mVisible=" + mVisible + " mClientVisible=" + isClientVisible() + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "") + " reportedDrawn=" + mReportedDrawn + " reportedVisible=" + reportedVisible); if (paused) { @@ -1695,7 +1692,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A keysPaused = false; inHistory = false; nowVisible = false; - mClientVisible = true; + super.setClientVisible(true); idle = false; hasBeenLaunched = false; mTaskSupervisor = supervisor; @@ -3735,7 +3732,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A setVisibleRequested(true); mVisibleSetFromTransferredStartingWindow = true; } - setClientVisible(fromActivity.mClientVisible); + setClientVisible(fromActivity.isClientVisible()); if (fromActivity.isAnimating()) { transferAnimation(fromActivity); @@ -5836,18 +5833,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return mReportedDrawn; } - boolean isClientVisible() { - return mClientVisible; - } - + @Override void setClientVisible(boolean clientVisible) { - if (mClientVisible == clientVisible || (!clientVisible && mDeferHidingClient)) { - return; - } + // TODO(shell-transitions): Remove mDeferHidingClient once everything is shell-transitions. + // pip activities should just remain in clientVisible. + if (!clientVisible && mDeferHidingClient) return; ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "setClientVisible: %s clientVisible=%b Callers=%s", this, clientVisible, Debug.getCallers(5)); - mClientVisible = clientVisible; + super.setClientVisible(clientVisible); sendAppVisibilityToClients(); } @@ -8134,7 +8128,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A proto.write(TRANSLUCENT, !occludesParent()); proto.write(VISIBLE, mVisible); proto.write(VISIBLE_REQUESTED, mVisibleRequested); - proto.write(CLIENT_VISIBLE, mClientVisible); + proto.write(CLIENT_VISIBLE, isClientVisible()); proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient); proto.write(REPORTED_DRAWN, mReportedDrawn); proto.write(REPORTED_VISIBLE, reportedVisible); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 1157307cf7b7..eada1e5d0e5c 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -4822,7 +4822,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } mNoAnimationNotifyOnTransitionFinished.clear(); - mWallpaperController.hideDeferredWallpapersIfNeeded(); + mWallpaperController.hideDeferredWallpapersIfNeededLegacy(); onAppTransitionDone(); diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java index 1f7e1524b702..316c20ba5c47 100644 --- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java +++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java @@ -99,6 +99,9 @@ class EnsureActivitiesVisibleHelper { mTask.forAllActivities(a -> { setActivityVisibilityState(a, starting, resumeTopActivity); }); + if (mTask.mAtmService.getTransitionController().getTransitionPlayer() != null) { + mTask.getDisplayContent().mWallpaperController.adjustWallpaperWindows(); + } } private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting, diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 98eb11f8a970..ee4c66d05eb4 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -135,6 +135,11 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe mSyncId = mSyncEngine.startSyncSet(this); } + @VisibleForTesting + int getSyncId() { + return mSyncId; + } + /** * Formally starts the transition. Participants can be collected before this is started, * but this won't consider itself ready until started -- even if all the participants have @@ -271,12 +276,17 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // Commit all going-invisible containers for (int i = 0; i < mParticipants.size(); ++i) { final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord(); - if (ar == null || ar.mVisibleRequested) { - continue; + if (ar != null && !ar.isVisibleRequested()) { + ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, + " Commit activity becoming invisible: %s", ar); + ar.commitVisibility(false /* visible */, false /* performLayout */); + } + final WallpaperWindowToken wt = mParticipants.valueAt(i).asWallpaperToken(); + if (wt != null && !wt.isVisibleRequested()) { + ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, + " Commit wallpaper becoming invisible: %s", ar); + wt.commitVisibility(false /* visible */); } - ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, - " Commit activity becoming invisible: %s", ar); - ar.commitVisibility(false /* visible */, false /* performLayout */); } } diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 1a3138d492c8..7c5afa8282ee 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -126,12 +126,18 @@ class WallpaperController { } mFindResults.resetTopWallpaper = true; - if (w.mActivityRecord != null && !w.mActivityRecord.isVisible() - && !w.mActivityRecord.isAnimating(TRANSITION | PARENTS)) { - - // If this window's app token is hidden and not animating, it is of no interest to us. - if (DEBUG_WALLPAPER) Slog.v(TAG, "Skipping hidden and not animating token: " + w); - return false; + if (mService.mAtmService.getTransitionController().getTransitionPlayer() == null) { + if (w.mActivityRecord != null && !w.mActivityRecord.isVisible() + && !w.mActivityRecord.isAnimating(TRANSITION | PARENTS)) { + // If this window's app token is hidden and not animating, it is of no interest. + if (DEBUG_WALLPAPER) Slog.v(TAG, "Skipping hidden and not animating token: " + w); + return false; + } + } else { + if (w.mActivityRecord != null && !w.mActivityRecord.isVisibleRequested()) { + // An activity that is not going to remain visible shouldn't be the target. + return false; + } } if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": isOnScreen=" + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState); @@ -227,7 +233,10 @@ class WallpaperController { } boolean isWallpaperVisible() { - return isWallpaperVisible(mWallpaperTarget); + for (int i = mWallpaperTokens.size() - 1; i >= 0; --i) { + if (mWallpaperTokens.get(i).isVisible()) return true; + } + return false; } /** @@ -240,7 +249,7 @@ class WallpaperController { } } - private boolean isWallpaperVisible(WindowState wallpaperTarget) { + private boolean shouldWallpaperBeVisible(WindowState wallpaperTarget) { if (DEBUG_WALLPAPER) { Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + " prev=" + mPrevWallpaperTarget); @@ -255,18 +264,18 @@ class WallpaperController { } void updateWallpaperVisibility() { - final boolean visible = isWallpaperVisible(mWallpaperTarget); + final boolean visible = shouldWallpaperBeVisible(mWallpaperTarget); for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) { final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx); - token.updateWallpaperVisibility(visible); + token.setVisibility(visible); } } - void hideDeferredWallpapersIfNeeded() { - if (mDeferredHideWallpaper != null) { - hideWallpapers(mDeferredHideWallpaper); - mDeferredHideWallpaper = null; + void hideDeferredWallpapersIfNeededLegacy() { + for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) { + final WallpaperWindowToken token = mWallpaperTokens.get(i); + token.commitVisibility(false); } } @@ -275,18 +284,9 @@ class WallpaperController { && (mWallpaperTarget != winGoingAway || mPrevWallpaperTarget != null)) { return; } - if (mWallpaperTarget != null - && mWallpaperTarget.getDisplayContent().mAppTransition.isRunning()) { - // Defer hiding the wallpaper when app transition is running until the animations - // are done. - mDeferredHideWallpaper = winGoingAway; - return; - } - - final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway); for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) { final WallpaperWindowToken token = mWallpaperTokens.get(i); - token.hideWallpaperToken(wasDeferred, "hideWallpapers"); + token.setVisibility(false); if (DEBUG_WALLPAPER_LIGHT && token.isVisible()) { Slog.d(TAG, "Hiding wallpaper " + token + " from " + winGoingAway + " target=" + mWallpaperTarget + " prev=" @@ -616,7 +616,7 @@ class WallpaperController { // The window is visible to the compositor...but is it visible to the user? // That is what the wallpaper cares about. - final boolean visible = mWallpaperTarget != null && isWallpaperVisible(mWallpaperTarget); + final boolean visible = mWallpaperTarget != null; if (DEBUG_WALLPAPER) { Slog.v(TAG, "Wallpaper visibility: " + visible + " at display " + mDisplayContent.getDisplayId()); diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java index 43303d4a5d7e..717775605c94 100644 --- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java +++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java @@ -19,7 +19,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; -import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -34,6 +34,8 @@ import android.view.ViewGroup; import android.view.WindowManager; import android.view.animation.Animation; +import com.android.internal.protolog.common.ProtoLog; + import java.util.function.Consumer; /** @@ -43,6 +45,8 @@ class WallpaperWindowToken extends WindowToken { private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperWindowToken" : TAG_WM; + private boolean mVisibleRequested = false; + WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit, DisplayContent dc, boolean ownerCanManageAppTokens) { this(service, token, explicit, dc, ownerCanManageAppTokens, null /* options */); @@ -57,18 +61,16 @@ class WallpaperWindowToken extends WindowToken { } @Override + WallpaperWindowToken asWallpaperToken() { + return this; + } + + @Override void setExiting() { super.setExiting(); mDisplayContent.mWallpaperController.removeWallpaperToken(this); } - void hideWallpaperToken(boolean wasDeferred, String reason) { - for (int j = mChildren.size() - 1; j >= 0; j--) { - final WindowState wallpaper = mChildren.get(j); - wallpaper.hideWallpaperWindow(wasDeferred, reason); - } - } - void sendWindowWallpaperCommand( String action, int x, int y, int z, Bundle extras, boolean sync) { for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) { @@ -93,24 +95,6 @@ class WallpaperWindowToken extends WindowToken { } } - void updateWallpaperVisibility(boolean visible) { - if (isVisible() != visible) { - mWmService.mAtmService.getTransitionController().collect(this); - // Need to do a layout to ensure the wallpaper now has the correct size. - mDisplayContent.setLayoutNeeded(); - } - - final WallpaperController wallpaperController = mDisplayContent.mWallpaperController; - for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) { - final WindowState wallpaper = mChildren.get(wallpaperNdx); - if (visible) { - wallpaperController.updateWallpaperOffset(wallpaper, false /* sync */); - } - - wallpaper.dispatchWallpaperVisibility(visible); - } - } - /** * Starts {@param anim} on all children. */ @@ -122,16 +106,16 @@ class WallpaperWindowToken extends WindowToken { } void updateWallpaperWindows(boolean visible) { - if (isVisible() != visible) { if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, "Wallpaper token " + token + " visible=" + visible); - mWmService.mAtmService.getTransitionController().collect(this); - // Need to do a layout to ensure the wallpaper now has the correct size. - mDisplayContent.setLayoutNeeded(); + setVisibility(visible); } - final WallpaperController wallpaperController = mDisplayContent.mWallpaperController; + if (mWmService.mAtmService.getTransitionController().getTransitionPlayer() != null) { + return; + } + final WindowState wallpaperTarget = wallpaperController.getWallpaperTarget(); if (visible && wallpaperTarget != null) { @@ -153,19 +137,52 @@ class WallpaperWindowToken extends WindowToken { } } - for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) { - final WindowState wallpaper = mChildren.get(wallpaperNdx); + setVisible(visible); + } - if (visible) { - wallpaperController.updateWallpaperOffset(wallpaper, false /* sync */); + private void setVisible(boolean visible) { + final boolean wasClientVisible = isClientVisible(); + setClientVisible(visible); + if (visible && !wasClientVisible) { + for (int i = mChildren.size() - 1; i >= 0; i--) { + final WindowState wallpaper = mChildren.get(i); + wallpaper.requestUpdateWallpaperIfNeeded(); } + } + } - // First, make sure the client has the current visibility state. - wallpaper.dispatchWallpaperVisibility(visible); + /** + * Sets the requested visibility of this token. The visibility may not be if this is part of a + * transition. In that situation, make sure to call {@link #commitVisibility} when done. + */ + void setVisibility(boolean visible) { + // Before setting mVisibleRequested so we can track changes. + mWmService.mAtmService.getTransitionController().collect(this); + + setVisibleRequested(visible); - if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win " - + wallpaper); + // If in a transition, defer commits for activities that are going invisible + if (!visible && (mWmService.mAtmService.getTransitionController().inTransition() + || getDisplayContent().mAppTransition.isRunning())) { + return; } + + commitVisibility(visible); + } + + /** + * Commits the visibility of this token. This will directly update the visibility without + * regard for other state (like being in a transition). + */ + void commitVisibility(boolean visible) { + if (visible == isVisible()) return; + + ProtoLog.v(WM_DEBUG_WINDOW_TRANSITIONS, + "commitVisibility: %s: visible=%b mVisibleRequested=%b", this, + isVisible(), mVisibleRequested); + + setVisibleRequested(visible); + setVisible(visible); } @Override @@ -186,9 +203,10 @@ class WallpaperWindowToken extends WindowToken { } boolean hasVisibleNotDrawnWallpaper() { + if (!isVisible()) return false; for (int j = mChildren.size() - 1; j >= 0; --j) { final WindowState wallpaper = mChildren.get(j); - if (wallpaper.hasVisibleNotDrawnWallpaper()) { + if (!wallpaper.isDrawn() && wallpaper.isVisible()) { return true; } } @@ -210,6 +228,21 @@ class WallpaperWindowToken extends WindowToken { return false; } + void setVisibleRequested(boolean visible) { + if (mVisibleRequested == visible) return; + mVisibleRequested = visible; + setInsetsFrozen(!visible); + } + + @Override + boolean isVisibleRequested() { + return mVisibleRequested; + } + + @Override + boolean isVisible() { + return isClientVisible(); + } @Override public String toString() { diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 000889a16d4c..0c4ff2fe6365 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -3060,6 +3060,11 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } /** Cheap way of doing cast and instanceof. */ + WallpaperWindowToken asWallpaperToken() { + return null; + } + + /** Cheap way of doing cast and instanceof. */ DisplayArea asDisplayArea() { 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 fec715ec7f79..deb3913a32ed 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -141,11 +141,9 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; -import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; -import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT; @@ -358,7 +356,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP private boolean mForceHideNonSystemOverlayWindow; boolean mAppFreezing; boolean mHidden = true; // Used to determine if to show child windows. - boolean mWallpaperVisible; // for wallpaper, what was last vis report? private boolean mDragResizing; private boolean mDragResizingChangeReported = true; private int mResizeMode; @@ -1715,7 +1712,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override boolean isVisibleRequested() { - return isVisible() && (mActivityRecord == null || mActivityRecord.isVisibleRequested()); + if (mToken != null && (mActivityRecord != null || mToken.asWallpaperToken() != null)) { + // Currently only ActivityRecord and WallpaperToken support visibleRequested. + return isVisible() && mToken.isVisibleRequested(); + } + return isVisible(); } /** @@ -1745,8 +1746,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * {@code false} otherwise. */ boolean wouldBeVisibleIfPolicyIgnored() { - return mHasSurface && !isParentWindowHidden() - && !mAnimatingExit && !mDestroying && (!mIsWallpaper || mWallpaperVisible); + if (!mHasSurface || isParentWindowHidden() || mAnimatingExit || mDestroying) { + return false; + } + final boolean isWallpaper = mToken != null && mToken.asWallpaperToken() != null; + return !isWallpaper || mToken.isVisible(); } /** @@ -1804,6 +1808,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return ((!isParentWindowHidden() && atoken.isVisible()) || isAnimating(TRANSITION | PARENTS)); } + final WallpaperWindowToken wtoken = mToken.asWallpaperToken(); + if (wtoken != null) { + return !isParentWindowHidden() && wtoken.isVisible(); + } return !isParentWindowHidden() || isAnimating(TRANSITION | PARENTS); } @@ -1943,8 +1951,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // When there is keyguard, wallpaper could be placed over the secure app // window but invisible. We need to check wallpaper visibility explicitly // to determine if it's occluding apps. - return ((!mIsWallpaper && mAttrs.format == PixelFormat.OPAQUE) - || (mIsWallpaper && mWallpaperVisible)) + final boolean isWallpaper = mToken != null && mToken.asWallpaperToken() != null; + return ((!isWallpaper && mAttrs.format == PixelFormat.OPAQUE) + || (isWallpaper && mToken.isVisible())) && isDrawn() && !isAnimating(TRANSITION | PARENTS); } @@ -3224,7 +3233,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP void sendAppVisibilityToClients() { super.sendAppVisibilityToClients(); - final boolean clientVisible = mActivityRecord.isClientVisible(); + if (mToken == null) return; + + final boolean clientVisible = mToken.isClientVisible(); + // TODO(shell-transitions): This is currently only applicable to app windows, BUT we + // want to extend the "starting" concept to other windows. if (mAttrs.type == TYPE_APPLICATION_STARTING && !clientVisible) { // Don't hide the starting window. return; @@ -3608,9 +3621,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (mActivityRecord != null && mActivityRecord.isRelaunching()) { return; } - // If the activity is invisible or going invisible, don't report either since it is going - // away. This is likely during a transition so we want to preserve the original state. - if (mActivityRecord != null && !mActivityRecord.isVisibleRequested()) { + // If this is an activity or wallpaper and is invisible or going invisible, don't report + // either since it is going away. This is likely during a transition so we want to preserve + // the original state. + if ((mActivityRecord != null || mToken.asWallpaperToken() != null) + && !mToken.isVisibleRequested()) { return; } @@ -4024,8 +4039,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) { pw.println(prefix + "mIsImWindow=" + mIsImWindow + " mIsWallpaper=" + mIsWallpaper - + " mIsFloatingLayer=" + mIsFloatingLayer - + " mWallpaperVisible=" + mWallpaperVisible); + + " mIsFloatingLayer=" + mIsFloatingLayer); } if (dumpAll) { pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer); @@ -4839,61 +4853,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; } - void hideWallpaperWindow(boolean wasDeferred, String reason) { - for (int j = mChildren.size() - 1; j >= 0; --j) { - final WindowState c = mChildren.get(j); - c.hideWallpaperWindow(wasDeferred, reason); - } - if (!mWinAnimator.mLastHidden || wasDeferred) { - mWinAnimator.hide(getGlobalTransaction(), reason); - getDisplayContent().mWallpaperController.mDeferredHideWallpaper = null; - dispatchWallpaperVisibility(false); - final DisplayContent displayContent = getDisplayContent(); - if (displayContent != null) { - displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; - if (DEBUG_LAYOUT_REPEATS) { - mWmService.mWindowPlacerLocked.debugLayoutRepeats("hideWallpaperWindow " + this, - displayContent.pendingLayoutChanges); - } - } - } - } - - /** - * Check wallpaper window for visibility change and notify window if so. - * @param visible Current visibility. - */ - void dispatchWallpaperVisibility(final boolean visible) { - final boolean hideAllowed = - getDisplayContent().mWallpaperController.mDeferredHideWallpaper == null; - - // Only send notification if the visibility actually changed and we are not trying to hide - // the wallpaper when we are deferring hiding of the wallpaper. - if (mWallpaperVisible != visible && (hideAllowed || visible)) { - mWallpaperVisible = visible; - try { - if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, - "Updating vis of wallpaper " + this - + ": " + visible + " from:\n" + Debug.getCallers(4, " ")); - mClient.dispatchAppVisibility(visible); - } catch (RemoteException e) { - } - } - } - - boolean hasVisibleNotDrawnWallpaper() { - if (mWallpaperVisible && !isDrawn()) { - return true; - } - for (int j = mChildren.size() - 1; j >= 0; --j) { - final WindowState c = mChildren.get(j); - if (c.hasVisibleNotDrawnWallpaper()) { - return true; - } - } - return false; - } - void updateReportedVisibility(UpdateReportedVisibilityResults results) { for (int i = mChildren.size() - 1; i >= 0; --i) { final WindowState c = mChildren.get(i); diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index ece256e8c591..ebbebbb702d8 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -57,7 +57,6 @@ import android.content.Context; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.Rect; -import android.graphics.Region; import android.os.Debug; import android.os.Trace; import android.util.Slog; @@ -575,10 +574,7 @@ class WindowStateAnimator { setSurfaceBoundariesLocked(t); - if (mIsWallpaper && !w.mWallpaperVisible) { - // Wallpaper is no longer visible and there is no wp target => hide it. - hide(t, "prepareSurfaceLocked"); - } else if (w.isParentWindowHidden() || !w.isOnScreen()) { + if (w.isParentWindowHidden() || !w.isOnScreen()) { hide(t, "prepareSurfaceLocked"); mWallpaperControllerLocked.hideWallpapers(w); @@ -631,9 +627,6 @@ class WindowStateAnimator { if (showSurfaceRobustlyLocked(t)) { mAnimator.requestRemovalOfReplacedWindows(w); mLastHidden = false; - if (mIsWallpaper) { - w.dispatchWallpaperVisibility(true); - } final DisplayContent displayContent = w.getDisplayContent(); if (!displayContent.getLastHasContent()) { // This draw means the difference between unique content and mirroring. diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 066cc1e105ab..8867aa747379 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT; import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; @@ -112,6 +113,9 @@ class WindowToken extends WindowContainer<WindowState> { */ private final boolean mFromClientToken; + /** Have we told the window clients to show themselves? */ + private boolean mClientVisible; + /** * Used to fix the transform of the token to be rotated to a rotation different than it's * display. The window frames and surfaces corresponding to this token will be layouted and @@ -397,6 +401,21 @@ class WindowToken extends WindowContainer<WindowState> { return builder; } + boolean isClientVisible() { + return mClientVisible; + } + + void setClientVisible(boolean clientVisible) { + if (mClientVisible == clientVisible) { + return; + } + ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, + "setClientVisible: %s clientVisible=%b Callers=%s", this, clientVisible, + Debug.getCallers(5)); + mClientVisible = clientVisible; + sendAppVisibilityToClients(); + } + boolean hasFixedRotationTransform() { return mFixedRotationTransformState != null; } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 137cf6523caf..09a436c59e7b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -518,6 +518,7 @@ public class DisplayContentTests extends WindowTestsBase { TYPE_WALLPAPER, TYPE_APPLICATION); final WindowState wallpaper = windows[0]; assertTrue(wallpaper.mIsWallpaper); + wallpaper.mToken.asWallpaperToken().setVisibility(false); // By default WindowState#mWallpaperVisible is false. assertFalse(wallpaper.isVisible()); 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 401ace03c554..154a899fb5ff 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -316,9 +316,9 @@ public class TransitionTests extends WindowTestsBase { mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */)); final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken, "wallpaperWindow"); - wallpaperWindow.mWallpaperVisible = false; + wallpaperWindowToken.setVisibleRequested(false); transition.collect(wallpaperWindowToken); - wallpaperWindow.mWallpaperVisible = true; + wallpaperWindowToken.setVisibleRequested(true); wallpaperWindow.mHasSurface = true; // doesn't matter which order collected since participants is a set diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java index d1d0ac68017a..8b4e94724e6c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java @@ -24,6 +24,8 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import static android.view.WindowManager.TRANSIT_CLOSE; +import static android.view.WindowManager.TRANSIT_OPEN; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; @@ -49,7 +51,9 @@ import android.view.Gravity; import android.view.InsetsState; import android.view.RoundedCorners; import android.view.Surface; +import android.view.SurfaceControl; import android.view.WindowManager; +import android.window.ITransitionPlayer; import androidx.test.filters.SmallTest; @@ -135,7 +139,8 @@ public class WallpaperControllerTests extends WindowTestsBase { int expectedWidth = (int) (wallpaperWidth * (displayHeight / (double) wallpaperHeight)); // Check that the wallpaper is correctly scaled - assertEquals(new Rect(0, 0, expectedWidth, displayHeight), wallpaperWindow.getFrame()); + assertEquals(expectedWidth, wallpaperWindow.getFrame().width()); + assertEquals(displayHeight, wallpaperWindow.getFrame().height()); Rect portraitFrame = wallpaperWindow.getFrame(); // Rotate the display @@ -297,6 +302,46 @@ public class WallpaperControllerTests extends WindowTestsBase { assertFalse(mAppWindow.mActivityRecord.hasFixedRotationTransform()); } + @Test + public void testWallpaperTokenVisibility() { + final DisplayContent dc = mWm.mRoot.getDefaultDisplay(); + final WallpaperWindowToken token = new WallpaperWindowToken(mWm, mock(IBinder.class), + true, dc, true /* ownerCanManageAppTokens */); + final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, token, + "wallpaperWindow"); + wallpaperWindow.setHasSurface(true); + + // Set-up mock shell transitions + final IBinder mockBinder = mock(IBinder.class); + final ITransitionPlayer mockPlayer = mock(ITransitionPlayer.class); + doReturn(mockBinder).when(mockPlayer).asBinder(); + mWm.mAtmService.getTransitionController().registerTransitionPlayer(mockPlayer); + + Transition transit = + mWm.mAtmService.getTransitionController().createTransition(TRANSIT_OPEN); + + // wallpaper windows are immediately visible when set to visible even during a transition + token.setVisibility(true); + assertTrue(wallpaperWindow.isVisible()); + assertTrue(token.isVisibleRequested()); + assertTrue(token.isVisible()); + mWm.mAtmService.getTransitionController().abort(transit); + + // In a transition, setting invisible should ONLY set requestedVisible false; otherwise + // wallpaper should remain "visible" until transition is over. + transit = mWm.mAtmService.getTransitionController().createTransition(TRANSIT_CLOSE); + transit.start(); + token.setVisibility(false); + assertTrue(wallpaperWindow.isVisible()); + assertFalse(token.isVisibleRequested()); + assertTrue(token.isVisible()); + + transit.onTransactionReady(transit.getSyncId(), mock(SurfaceControl.Transaction.class)); + transit.finishTransition(); + assertFalse(wallpaperWindow.isVisible()); + assertFalse(token.isVisible()); + } + private WindowState createWallpaperTargetWindow(DisplayContent dc) { final ActivityRecord homeActivity = new ActivityBuilder(mWm.mAtmService) .setTask(dc.getDefaultTaskDisplayArea().getRootHomeTask()) diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index ebc5c4ff280a..1f38f463a7d3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -245,6 +245,9 @@ class WindowTestsBase extends SystemServiceTestsBase { private WindowToken createWindowToken( DisplayContent dc, int windowingMode, int activityType, int type) { + if (type == TYPE_WALLPAPER) { + return createWallpaperToken(dc); + } if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) { return createTestWindowToken(type, dc); } @@ -252,6 +255,11 @@ class WindowTestsBase extends SystemServiceTestsBase { return createActivityRecord(dc, windowingMode, activityType); } + private WindowToken createWallpaperToken(DisplayContent dc) { + return new WallpaperWindowToken(mWm, mock(IBinder.class), true /* explicit */, dc, + true /* ownerCanManageAppTokens */); + } + WindowState createAppWindow(Task task, int type, String name) { final ActivityRecord activity = createNonAttachedActivityRecord(task.getDisplayContent()); task.addChild(activity, 0); |