|
| 1 | +From 0f3219b2ffd7a834b96cff0e84a5f3fa97d310da Mon Sep 17 00:00:00 2001 |
| 2 | +From: wilsonshih <wilsonshih@google.com> |
| 3 | +Date: Tue, 31 Dec 2024 08:25:26 +0000 |
| 4 | +Subject: [PATCH] Defer remove splash screen while device is locked |
| 5 | + |
| 6 | +...and activity does not request showWhenLocked. |
| 7 | +The splash screen won't contains secure information, so it's safe to |
| 8 | +declared as showWhenLocked. But before remove starting window, if the |
| 9 | +activity does not request showWhenLocked and device is locked, try to |
| 10 | +trigger unoccluding animation, and keep app window hide until transition |
| 11 | +animation finish. |
| 12 | + |
| 13 | +Bug: 378088391 |
| 14 | +Bug: 383131643 |
| 15 | +Test: run simulate app repeatly, verify the app content won't be visible |
| 16 | +during transition animation. |
| 17 | + |
| 18 | +Merged-In: Ia2ddece125521eefb15d67e22ea863dfae6af112 |
| 19 | +Change-Id: Ia2ddece125521eefb15d67e22ea863dfae6af112 |
| 20 | +--- |
| 21 | + .../com/android/server/wm/ActivityRecord.java | 24 +++++++++++++++++++ |
| 22 | + .../com/android/server/wm/StartingData.java | 7 ++++++ |
| 23 | + .../com/android/server/wm/Transition.java | 9 +++++++ |
| 24 | + .../com/android/server/wm/WindowState.java | 15 ++++++++++++ |
| 25 | + 4 files changed, 55 insertions(+) |
| 26 | + |
| 27 | +diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java |
| 28 | +index 3b582924ec96..88d0ad67fb21 100644 |
| 29 | +--- a/services/core/java/com/android/server/wm/ActivityRecord.java |
| 30 | ++++ b/services/core/java/com/android/server/wm/ActivityRecord.java |
| 31 | +@@ -230,6 +230,7 @@ import static com.android.server.wm.IdentifierProto.USER_ID; |
| 32 | + import static com.android.server.wm.StartingData.AFTER_TRANSACTION_COPY_TO_CLIENT; |
| 33 | + import static com.android.server.wm.StartingData.AFTER_TRANSACTION_IDLE; |
| 34 | + import static com.android.server.wm.StartingData.AFTER_TRANSACTION_REMOVE_DIRECTLY; |
| 35 | ++import static com.android.server.wm.StartingData.AFTER_TRANSITION_FINISH; |
| 36 | + import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; |
| 37 | + import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_PREDICT_BACK; |
| 38 | + import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; |
| 39 | +@@ -2809,9 +2810,28 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A |
| 40 | + attachStartingSurfaceToAssociatedTask(); |
| 41 | + } |
| 42 | + |
| 43 | ++ /** |
| 44 | ++ * If the device is locked and the app does not request showWhenLocked, |
| 45 | ++ * defer removing the starting window until the transition is complete. |
| 46 | ++ * This prevents briefly appearing the app context and causing secure concern. |
| 47 | ++ */ |
| 48 | ++ void deferStartingWindowRemovalForKeyguardUnoccluding() { |
| 49 | ++ if (mStartingData != null |
| 50 | ++ && mStartingData.mRemoveAfterTransaction != AFTER_TRANSITION_FINISH |
| 51 | ++ && isKeyguardLocked() && !canShowWhenLockedInner(this) && !isVisibleRequested() |
| 52 | ++ && mTransitionController.inTransition(this)) { |
| 53 | ++ mStartingData.mRemoveAfterTransaction = AFTER_TRANSITION_FINISH; |
| 54 | ++ } |
| 55 | ++ } |
| 56 | ++ |
| 57 | + void removeStartingWindow() { |
| 58 | + boolean prevEligibleForLetterboxEducation = isEligibleForLetterboxEducation(); |
| 59 | + |
| 60 | ++ if (mStartingData != null |
| 61 | ++ && mStartingData.mRemoveAfterTransaction == AFTER_TRANSITION_FINISH) { |
| 62 | ++ return; |
| 63 | ++ } |
| 64 | ++ |
| 65 | + if (transferSplashScreenIfNeeded()) { |
| 66 | + return; |
| 67 | + } |
| 68 | +@@ -4657,6 +4677,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | ++ if (mStartingData.mRemoveAfterTransaction == AFTER_TRANSITION_FINISH) { |
| 73 | ++ mStartingData.mRemoveAfterTransaction = AFTER_TRANSACTION_IDLE; |
| 74 | ++ } |
| 75 | ++ |
| 76 | + ProtoLog.v(WM_DEBUG_ADD_REMOVE, |
| 77 | + "Removing starting %s from %s", tStartingWindow, fromActivity); |
| 78 | + mTransitionController.collect(tStartingWindow); |
| 79 | +diff --git a/services/core/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java |
| 80 | +index 896612d3d27a..282637dede7e 100644 |
| 81 | +--- a/services/core/java/com/android/server/wm/StartingData.java |
| 82 | ++++ b/services/core/java/com/android/server/wm/StartingData.java |
| 83 | +@@ -31,11 +31,18 @@ public abstract class StartingData { |
| 84 | + static final int AFTER_TRANSACTION_REMOVE_DIRECTLY = 1; |
| 85 | + /** Do copy splash screen to client after transaction done. */ |
| 86 | + static final int AFTER_TRANSACTION_COPY_TO_CLIENT = 2; |
| 87 | ++ /** |
| 88 | ++ * Remove the starting window after transition finish. |
| 89 | ++ * Used when activity doesn't request show when locked, so the app window should never show to |
| 90 | ++ * the user if device is locked. |
| 91 | ++ **/ |
| 92 | ++ static final int AFTER_TRANSITION_FINISH = 3; |
| 93 | + |
| 94 | + @IntDef(prefix = { "AFTER_TRANSACTION" }, value = { |
| 95 | + AFTER_TRANSACTION_IDLE, |
| 96 | + AFTER_TRANSACTION_REMOVE_DIRECTLY, |
| 97 | + AFTER_TRANSACTION_COPY_TO_CLIENT, |
| 98 | ++ AFTER_TRANSITION_FINISH, |
| 99 | + }) |
| 100 | + @interface AfterTransaction {} |
| 101 | + |
| 102 | +diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java |
| 103 | +index 1fc609b7d03a..dcced3ddbde7 100644 |
| 104 | +--- a/services/core/java/com/android/server/wm/Transition.java |
| 105 | ++++ b/services/core/java/com/android/server/wm/Transition.java |
| 106 | +@@ -73,6 +73,8 @@ import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_W |
| 107 | + import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_PREDICT_BACK; |
| 108 | + import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; |
| 109 | + import static com.android.server.wm.WindowState.BLAST_TIMEOUT_DURATION; |
| 110 | ++import static com.android.server.wm.StartingData.AFTER_TRANSACTION_IDLE; |
| 111 | ++import static com.android.server.wm.StartingData.AFTER_TRANSITION_FINISH; |
| 112 | + import static com.android.window.flags.Flags.enableDisplayFocusInShellTransitions; |
| 113 | + |
| 114 | + import android.annotation.IntDef; |
| 115 | +@@ -1377,6 +1379,13 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { |
| 116 | + enterAutoPip = true; |
| 117 | + } |
| 118 | + } |
| 119 | ++ |
| 120 | ++ if (ar.mStartingData != null && ar.mStartingData.mRemoveAfterTransaction |
| 121 | ++ == AFTER_TRANSITION_FINISH |
| 122 | ++ && (!ar.isVisible() || !ar.mTransitionController.inTransition(ar))) { |
| 123 | ++ ar.mStartingData.mRemoveAfterTransaction = AFTER_TRANSACTION_IDLE; |
| 124 | ++ ar.removeStartingWindow(); |
| 125 | ++ } |
| 126 | + final ChangeInfo changeInfo = mChanges.get(ar); |
| 127 | + // Due to transient-hide, there may be some activities here which weren't in the |
| 128 | + // transition. |
| 129 | +diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java |
| 130 | +index cebe790bb1b9..3fa1130d86a3 100644 |
| 131 | +--- a/services/core/java/com/android/server/wm/WindowState.java |
| 132 | ++++ b/services/core/java/com/android/server/wm/WindowState.java |
| 133 | +@@ -126,6 +126,7 @@ import static com.android.server.wm.IdentifierProto.USER_ID; |
| 134 | + import static com.android.server.wm.MoveAnimationSpecProto.DURATION_MS; |
| 135 | + import static com.android.server.wm.MoveAnimationSpecProto.FROM; |
| 136 | + import static com.android.server.wm.MoveAnimationSpecProto.TO; |
| 137 | ++import static com.android.server.wm.StartingData.AFTER_TRANSITION_FINISH; |
| 138 | + import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; |
| 139 | + import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; |
| 140 | + import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_STARTING_REVEAL; |
| 141 | +@@ -1920,6 +1921,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP |
| 142 | + } |
| 143 | + final ActivityRecord atoken = mActivityRecord; |
| 144 | + if (atoken != null) { |
| 145 | ++ if (atoken.mStartingData != null && mAttrs.type != TYPE_APPLICATION_STARTING |
| 146 | ++ && atoken.mStartingData.mRemoveAfterTransaction |
| 147 | ++ == AFTER_TRANSITION_FINISH) { |
| 148 | ++ // Preventing app window from visible during un-occluding animation playing due to |
| 149 | ++ // alpha blending. |
| 150 | ++ return false; |
| 151 | ++ } |
| 152 | + final boolean isVisible = isStartingWindowAssociatedToTask() |
| 153 | + ? mStartingData.mAssociatedTask.isVisible() : atoken.isVisible(); |
| 154 | + return ((!isParentWindowHidden() && isVisible) |
| 155 | +@@ -2925,7 +2933,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP |
| 156 | + final int mask = FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD |
| 157 | + | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; |
| 158 | + WindowManager.LayoutParams sa = mActivityRecord.mStartingWindow.mAttrs; |
| 159 | ++ final boolean wasShowWhenLocked = (sa.flags & FLAG_SHOW_WHEN_LOCKED) != 0; |
| 160 | ++ final boolean removeShowWhenLocked = (mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0; |
| 161 | + sa.flags = (sa.flags & ~mask) | (mAttrs.flags & mask); |
| 162 | ++ if (wasShowWhenLocked && removeShowWhenLocked) { |
| 163 | ++ // Trigger unoccluding animation if needed. |
| 164 | ++ mActivityRecord.checkKeyguardFlagsChanged(); |
| 165 | ++ mActivityRecord.deferStartingWindowRemovalForKeyguardUnoccluding(); |
| 166 | ++ } |
| 167 | + } |
| 168 | + } |
| 169 | + |
| 170 | +-- |
| 171 | +2.34.1 |
| 172 | + |
0 commit comments