Loading core/java/android/window/flags/windowing_frontend.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,17 @@ flag { } } flag { name: "respect_hierarchy_surface_visibility" namespace: "windowing_frontend" description: "Ensure consistent surface visibility with window hierarchy" bug: "383241933" is_fixed_read_only: true metadata { purpose: PURPOSE_BUGFIX } } flag { name: "use_cached_insets_for_display_switch" namespace: "windowing_frontend" Loading services/core/java/com/android/server/wm/ActivityRecord.java +27 −2 Original line number Diff line number Diff line Loading @@ -5544,6 +5544,7 @@ final class ActivityRecord extends WindowToken { mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked( token); } mWmService.mAnimator.addSurfaceVisibilityUpdateIncludingAnimatableParents(this); } } Loading Loading @@ -7191,6 +7192,15 @@ final class ActivityRecord extends WindowToken { @Override void prepareSurfaces() { if (mWmService.mFlags.mEnsureSurfaceVisibility) { // Input sink surface is not a part of animation, so apply in a steady state // (non-sync) with pending transaction. if (mVisible && mSyncState == SYNC_STATE_NONE) { mActivityRecordInputSink.applyChangesToSurfaceIfChanged(getPendingTransaction()); } super.prepareSurfaces(); return; } final boolean isDecorSurfaceBoosted = getTask() != null && getTask().isDecorSurfaceBoosted(); final boolean show = (isVisible() Loading @@ -7216,6 +7226,15 @@ final class ActivityRecord extends WindowToken { super.prepareSurfaces(); } @Override void updateSurfaceVisibility(Transaction t) { final boolean visible = mVisible // Ensure that the activity content is hidden when the decor surface is boosted to // prevent UI redressing attack. && (task == null || !task.isDecorSurfaceBoosted()); t.setVisibility(mSurfaceControl, visible); } /** * @return Whether our {@link #getSurfaceControl} is currently showing. */ Loading Loading @@ -9453,9 +9472,15 @@ final class ActivityRecord extends WindowToken { } boolean canCaptureSnapshot() { if (mWmService.mFlags.mEnsureSurfaceVisibility) { if (!mVisible) { return false; } } else { if (!isSurfaceShowing() || findMainWindow() == null) { return false; } } return forAllWindows( // Ensure at least one window for the top app is visible before attempting to // take a screenshot. Visible here means that the WSA surface is shown and has Loading services/core/java/com/android/server/wm/BackNavigationController.java +2 −1 Original line number Diff line number Diff line Loading @@ -1895,7 +1895,8 @@ class BackNavigationController { } } // Force update mLastSurfaceShowing for opening activity and its task. if (mWindowManagerService.mRoot.mTransitionController.isShellTransitionsEnabled()) { if (mWindowManagerService.mRoot.mTransitionController.isShellTransitionsEnabled() && !mWindowManagerService.mFlags.mEnsureSurfaceVisibility) { for (int i = visibleOpenActivities.length - 1; i >= 0; --i) { WindowContainer.enforceSurfaceVisible(visibleOpenActivities[i]); } Loading services/core/java/com/android/server/wm/Task.java +20 −3 Original line number Diff line number Diff line Loading @@ -3297,6 +3297,10 @@ class Task extends TaskFragment { scheduleAnimation(); } if (mWmService.mFlags.mEnsureSurfaceVisibility) { return; } // Let organizer manage task visibility for shell transition. So don't change it's // visibility during collecting. if (mTransitionController.isCollecting() && mCreatedByOrganizer) { Loading @@ -3320,6 +3324,11 @@ class Task extends TaskFragment { mLastSurfaceShowing = show; } @Override void updateSurfaceVisibility(SurfaceControl.Transaction t) { t.setVisibility(mSurfaceControl, isVisible()); } /** * Fills in a {@link TaskInfo} with information from this task. Note that the base intent in the * task info will not include any extras or clip data. Loading Loading @@ -3690,8 +3699,9 @@ class Task extends TaskFragment { } mDecorSurfaceContainer.commitBoostedState(); // assignChildLayers() calls scheduleAnimation(), which calls prepareSurfaces() // to ensure child surface visibility. forAllActivities(mWmService.mAnimator::addSurfaceVisibilityUpdate, true /* traverseTopToBottom */); // This calls scheduleAnimation(), then WindowAnimator will update surface visibility. assignChildLayers(); } Loading Loading @@ -4784,7 +4794,14 @@ class Task extends TaskFragment { // rotation change) after leaving this scope, the visibility operation will be // put in sync transaction, then it is not synced with reparent. if (lastParentBeforePip.mSyncState == SYNC_STATE_NONE) { if (mWmService.mFlags.mEnsureSurfaceVisibility) { if (lastParentBeforePip.isVisible()) { lastParentBeforePip.getPendingTransaction().show( lastParentBeforePip.mSurfaceControl); } } else { lastParentBeforePip.prepareSurfaces(); } // If the moveToFront is a part of finishing transition, then make sure // the z-order of tasks are up-to-date. if (topActivity.mTransitionController.inFinishingTransition(topActivity)) { Loading services/core/java/com/android/server/wm/Transition.java +9 −1 Original line number Diff line number Diff line Loading @@ -1834,6 +1834,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } mConfigAtEndActivities = null; } ensureParticipantSurfaceVisibility(); primaryDisplay.getPendingTransaction().merge(transaction); primaryDisplay.scheduleAnimation(); mSyncId = -1; Loading Loading @@ -2041,6 +2042,13 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } } void ensureParticipantSurfaceVisibility() { for (int i = mParticipants.size() - 1; i >= 0; i--) { mController.mAtm.mWindowManager.mAnimator.addSurfaceVisibilityUpdate( mParticipants.valueAt(i)); } } @VisibleForTesting void overrideAnimationOptionsToInfoIfNecessary(@NonNull TransitionInfo info) { if (mOverrideOptions == null) { Loading Loading @@ -2527,7 +2535,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } /** Returns the parent that the remote animator can animate or control. */ private static WindowContainer<?> getAnimatableParent(WindowContainer<?> wc) { static WindowContainer<?> getAnimatableParent(WindowContainer<?> wc) { WindowContainer<?> parent = wc.getParent(); while (parent != null && (!parent.canCreateRemoteAnimationTarget() && !parent.isOrganized())) { Loading Loading
core/java/android/window/flags/windowing_frontend.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,17 @@ flag { } } flag { name: "respect_hierarchy_surface_visibility" namespace: "windowing_frontend" description: "Ensure consistent surface visibility with window hierarchy" bug: "383241933" is_fixed_read_only: true metadata { purpose: PURPOSE_BUGFIX } } flag { name: "use_cached_insets_for_display_switch" namespace: "windowing_frontend" Loading
services/core/java/com/android/server/wm/ActivityRecord.java +27 −2 Original line number Diff line number Diff line Loading @@ -5544,6 +5544,7 @@ final class ActivityRecord extends WindowToken { mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked( token); } mWmService.mAnimator.addSurfaceVisibilityUpdateIncludingAnimatableParents(this); } } Loading Loading @@ -7191,6 +7192,15 @@ final class ActivityRecord extends WindowToken { @Override void prepareSurfaces() { if (mWmService.mFlags.mEnsureSurfaceVisibility) { // Input sink surface is not a part of animation, so apply in a steady state // (non-sync) with pending transaction. if (mVisible && mSyncState == SYNC_STATE_NONE) { mActivityRecordInputSink.applyChangesToSurfaceIfChanged(getPendingTransaction()); } super.prepareSurfaces(); return; } final boolean isDecorSurfaceBoosted = getTask() != null && getTask().isDecorSurfaceBoosted(); final boolean show = (isVisible() Loading @@ -7216,6 +7226,15 @@ final class ActivityRecord extends WindowToken { super.prepareSurfaces(); } @Override void updateSurfaceVisibility(Transaction t) { final boolean visible = mVisible // Ensure that the activity content is hidden when the decor surface is boosted to // prevent UI redressing attack. && (task == null || !task.isDecorSurfaceBoosted()); t.setVisibility(mSurfaceControl, visible); } /** * @return Whether our {@link #getSurfaceControl} is currently showing. */ Loading Loading @@ -9453,9 +9472,15 @@ final class ActivityRecord extends WindowToken { } boolean canCaptureSnapshot() { if (mWmService.mFlags.mEnsureSurfaceVisibility) { if (!mVisible) { return false; } } else { if (!isSurfaceShowing() || findMainWindow() == null) { return false; } } return forAllWindows( // Ensure at least one window for the top app is visible before attempting to // take a screenshot. Visible here means that the WSA surface is shown and has Loading
services/core/java/com/android/server/wm/BackNavigationController.java +2 −1 Original line number Diff line number Diff line Loading @@ -1895,7 +1895,8 @@ class BackNavigationController { } } // Force update mLastSurfaceShowing for opening activity and its task. if (mWindowManagerService.mRoot.mTransitionController.isShellTransitionsEnabled()) { if (mWindowManagerService.mRoot.mTransitionController.isShellTransitionsEnabled() && !mWindowManagerService.mFlags.mEnsureSurfaceVisibility) { for (int i = visibleOpenActivities.length - 1; i >= 0; --i) { WindowContainer.enforceSurfaceVisible(visibleOpenActivities[i]); } Loading
services/core/java/com/android/server/wm/Task.java +20 −3 Original line number Diff line number Diff line Loading @@ -3297,6 +3297,10 @@ class Task extends TaskFragment { scheduleAnimation(); } if (mWmService.mFlags.mEnsureSurfaceVisibility) { return; } // Let organizer manage task visibility for shell transition. So don't change it's // visibility during collecting. if (mTransitionController.isCollecting() && mCreatedByOrganizer) { Loading @@ -3320,6 +3324,11 @@ class Task extends TaskFragment { mLastSurfaceShowing = show; } @Override void updateSurfaceVisibility(SurfaceControl.Transaction t) { t.setVisibility(mSurfaceControl, isVisible()); } /** * Fills in a {@link TaskInfo} with information from this task. Note that the base intent in the * task info will not include any extras or clip data. Loading Loading @@ -3690,8 +3699,9 @@ class Task extends TaskFragment { } mDecorSurfaceContainer.commitBoostedState(); // assignChildLayers() calls scheduleAnimation(), which calls prepareSurfaces() // to ensure child surface visibility. forAllActivities(mWmService.mAnimator::addSurfaceVisibilityUpdate, true /* traverseTopToBottom */); // This calls scheduleAnimation(), then WindowAnimator will update surface visibility. assignChildLayers(); } Loading Loading @@ -4784,7 +4794,14 @@ class Task extends TaskFragment { // rotation change) after leaving this scope, the visibility operation will be // put in sync transaction, then it is not synced with reparent. if (lastParentBeforePip.mSyncState == SYNC_STATE_NONE) { if (mWmService.mFlags.mEnsureSurfaceVisibility) { if (lastParentBeforePip.isVisible()) { lastParentBeforePip.getPendingTransaction().show( lastParentBeforePip.mSurfaceControl); } } else { lastParentBeforePip.prepareSurfaces(); } // If the moveToFront is a part of finishing transition, then make sure // the z-order of tasks are up-to-date. if (topActivity.mTransitionController.inFinishingTransition(topActivity)) { Loading
services/core/java/com/android/server/wm/Transition.java +9 −1 Original line number Diff line number Diff line Loading @@ -1834,6 +1834,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } mConfigAtEndActivities = null; } ensureParticipantSurfaceVisibility(); primaryDisplay.getPendingTransaction().merge(transaction); primaryDisplay.scheduleAnimation(); mSyncId = -1; Loading Loading @@ -2041,6 +2042,13 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } } void ensureParticipantSurfaceVisibility() { for (int i = mParticipants.size() - 1; i >= 0; i--) { mController.mAtm.mWindowManager.mAnimator.addSurfaceVisibilityUpdate( mParticipants.valueAt(i)); } } @VisibleForTesting void overrideAnimationOptionsToInfoIfNecessary(@NonNull TransitionInfo info) { if (mOverrideOptions == null) { Loading Loading @@ -2527,7 +2535,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } /** Returns the parent that the remote animator can animate or control. */ private static WindowContainer<?> getAnimatableParent(WindowContainer<?> wc) { static WindowContainer<?> getAnimatableParent(WindowContainer<?> wc) { WindowContainer<?> parent = wc.getParent(); while (parent != null && (!parent.canCreateRemoteAnimationTarget() && !parent.isOrganized())) { Loading