diff options
15 files changed, 254 insertions, 166 deletions
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 30c2fce4a1ee..b7bf8ab75799 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", @@ -1831,6 +1837,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 +2473,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 ee980317c04e..55625809b632 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -581,9 +581,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; @@ -999,7 +996,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) { @@ -1736,7 +1733,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; @@ -3776,7 +3773,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A setVisibleRequested(true); mVisibleSetFromTransferredStartingWindow = true; } - setClientVisible(fromActivity.mClientVisible); + setClientVisible(fromActivity.isClientVisible()); if (fromActivity.isAnimating()) { transferAnimation(fromActivity); @@ -5877,18 +5874,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(); } @@ -8186,7 +8180,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 84bc8538f163..168ab43f4a9a 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -4823,7 +4823,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); |