Loading data/etc/services.core.protolog.json +12 −18 Original line number Diff line number Diff line Loading @@ -79,12 +79,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "-1976550065": { "message": "commitVisibility: %s: visible=%b visibleRequested=%b", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "-1963461591": { "message": "Removing %s from %s", "level": "VERBOSE", Loading Loading @@ -283,6 +277,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "-1521427940": { "message": "commitVisibility: %s: visible=%b mVisibleRequested=%b", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "-1515151503": { "message": ">>> OPEN TRANSACTION removeReplacedWindows", "level": "INFO", Loading Loading @@ -697,12 +697,6 @@ "group": "WM_DEBUG_SCREEN_ON", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-633961578": { "message": "applyAnimation: transition animation is disabled or skipped. container=%s", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "-622997754": { "message": "postWindowRemoveCleanupLocked: %s", "level": "VERBOSE", Loading Loading @@ -1477,12 +1471,6 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, "841702299": { "message": "Changing app %s visible=%b performLayout=%b", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "845234215": { "message": "App is requesting an orientation, return %d for display id=%d", "level": "VERBOSE", Loading Loading @@ -1993,6 +1981,12 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, "1967975839": { "message": "Changing app %s visible=%b performLayout=%b", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/AppTransitionController.java" }, "1984470582": { "message": "Creating TaskScreenshotAnimatable: task: %s width: %d height: %d", "level": "DEBUG", Loading services/core/java/com/android/server/wm/ActivityRecord.java +158 −152 Original line number Diff line number Diff line Loading @@ -547,7 +547,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults = new WindowState.UpdateReportedVisibilityResults(); private boolean mUseTransferredAnimation; boolean mUseTransferredAnimation; /** * @see #currentLaunchCanTurnScreenOn() Loading Loading @@ -2190,7 +2190,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** * Sets if this AWT is in the process of closing or entering PIP. * Sets if this {@link ActivityRecord} is in the process of closing or entering PIP. * {@link #mWillCloseOrEnterPip}} */ void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) { Loading @@ -2198,7 +2198,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** * Returns whether this AWT is considered closing. Conditions are either * Returns whether this {@link ActivityRecord} is considered closing. Conditions are either * 1. Is this app animating and was requested to be hidden * 2. App is delayed closing since it might enter PIP. */ Loading Loading @@ -3000,7 +3000,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this); boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction); commitVisibility(false /* visible */, true /* performLayout */); getDisplayContent().mOpeningApps.remove(this); getDisplayContent().mChangingApps.remove(this); Loading @@ -3008,6 +3008,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mWmService.mTaskSnapshotController.onAppRemoved(this); mStackSupervisor.getActivityMetricsLogger().notifyActivityRemoved(this); waitingToShow = false; boolean delayed = isAnimating(TRANSITION | CHILDREN); if (getDisplayContent().mClosingApps.contains(this)) { delayed = true; } else if (getDisplayContent().mAppTransition.isTransitionSet()) { Loading Loading @@ -3152,16 +3154,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A updateLetterboxSurface(child); } private boolean waitingForReplacement() { for (int i = mChildren.size() - 1; i >= 0; i--) { final WindowState candidate = mChildren.get(i); if (candidate.waitingForReplacement()) { return true; } } return false; } void onWindowReplacementTimeout() { for (int i = mChildren.size() - 1; i >= 0; --i) { (mChildren.get(i)).onWindowReplacementTimeout(); Loading Loading @@ -3417,7 +3409,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // before the non-exiting app tokens. So, we skip the exiting app tokens here. // TODO: Investigate if we need to continue to do this or if we can just process them // in-order. if (mIsExiting && !waitingForReplacement()) { if (mIsExiting && !forAllWindowsUnchecked(WindowState::waitingForReplacement, true)) { return false; } return forAllWindowsUnchecked(callback, traverseTopToBottom); Loading Loading @@ -3862,6 +3854,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } /** * Set visibility on this {@link ActivityRecord} * * <p class="note"><strong>Note: </strong>This function might not update the visibility of * this {@link ActivityRecord} immediately. In case we are preparing an app transition, we * delay changing the visibility of this {@link ActivityRecord} until we execute that * transition.</p> * * @param visible {@code true} if the {@link ActivityRecord} should become visible, otherwise * this should become invisible. */ void setVisibility(boolean visible) { if (getParent() == null) { Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " Loading Loading @@ -3998,62 +4001,45 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return; } commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction); commitVisibility(visible, true /* performLayout */); updateReportedVisibilityLocked(); } boolean commitVisibility(WindowManager.LayoutParams lp, boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) { boolean delayed = false; // Reset the state of mVisibleSetFromTransferredStartingWindow since visibility is actually // been set by the app now. mVisibleSetFromTransferredStartingWindow = false; // Allow for state changes and animation to be applied if: // * token is transitioning visibility state // * or the token was marked as hidden and is exiting before we had a chance to play the // transition animation // * or this is an opening app and windows are being replaced // * or the token is the opening app and visible while opening task behind existing one. final DisplayContent displayContent = getDisplayContent(); boolean visibilityChanged = false; if (isVisible() != visible || (!isVisible() && mIsExiting) || (visible && waitingForReplacement()) || (visible && displayContent.mOpeningApps.contains(this) && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) { final AccessibilityController accessibilityController = mWmService.mAccessibilityController; boolean changed = false; ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Changing app %s visible=%b performLayout=%b", this, isVisible(), performLayout); boolean runningAppAnimation = false; if (transit != WindowManager.TRANSIT_UNSET) { @Override boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) { if (mUseTransferredAnimation) { runningAppAnimation = isAnimating(); } else if (applyAnimation(lp, transit, visible, isVoiceInteraction)) { runningAppAnimation = true; return false; } delayed = runningAppAnimation; final WindowState window = findMainWindow(); if (window != null && accessibilityController != null) { accessibilityController.onAppWindowTransitionLocked(window, transit); return super.applyAnimation(lp, transit, enter, isVoiceInteraction); } changed = true; /** * Update visibility to this {@link ActivityRecord}. * * <p class="note"><strong>Note: </strong> Unlike {@link #setVisibility}, this immediately * updates the visibility without starting an app transition. Since this function may start * animation on {@link WindowState} depending on app transition animation status, an app * transition animation must be started before calling this function if necessary.</p> * * @param visible {@code true} if this {@link ActivityRecord} should become visible, otherwise * this should become invisible. * @param performLayout if {@code true}, perform surface placement after committing visibility. */ void commitVisibility(boolean visible, boolean performLayout) { // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually // been set by the app now. mVisibleSetFromTransferredStartingWindow = false; if (visible == isVisible()) { return; } final int windowsCount = mChildren.size(); for (int i = 0; i < windowsCount; i++) { final WindowState win = mChildren.get(i); changed |= win.onAppVisibilityChanged(visible, runningAppAnimation); mChildren.get(i).onAppVisibilityChanged(visible, isAnimating(PARENTS)); } setVisible(visible); mVisibleRequested = visible; visibilityChanged = true; if (!visible) { stopFreezingScreen(true, true); } else { Loading @@ -4063,17 +4049,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY); startingWindow.mLegacyPolicyVisibilityAfterAnim = false; } // We are becoming visible, so better freeze the screen with the windows that are // getting visible so we also wait for them. forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true); } ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "commitVisibility: %s: visible=%b visibleRequested=%b", this, "commitVisibility: %s: visible=%b mVisibleRequested=%b", this, isVisible(), mVisibleRequested); if (changed) { final DisplayContent displayContent = getDisplayContent(); displayContent.getInputMonitor().setUpdateInputWindowsNeededLw(); if (performLayout) { mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, Loading @@ -4081,36 +4064,46 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mWmService.mWindowPlacerLocked.performSurfacePlacement(); } displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/); } } mUseTransferredAnimation = false; delayed = isAnimating(CHILDREN); postApplyAnimation(visible); } /** * Post process after applying an app transition animation. * * <p class="note"><strong>Note: </strong> This function must be called after the animations * have been applied and {@link #commitVisibility}.</p> * * @param visible {@code true} if this {@link ActivityRecord} has become visible, otherwise * this has become invisible. */ private void postApplyAnimation(boolean visible) { final boolean delayed = isAnimating(PARENTS | CHILDREN); if (!delayed) { // We aren't animating anything, but exiting windows rely on the animation finished // callback being called in case the ActivityRecord was pretending to be animating, // We aren't delayed anything, but exiting windows rely on the animation finished // callback being called in case the ActivityRecord was pretending to be delayed, // which we might have done because we were in closing/opening apps list. onAnimationFinished(); } if (visibilityChanged) { if (visible && !delayed) { if (visible) { // The token was made immediately visible, there will be no entrance animation. // We need to inform the client the enter animation was finished. mEnteringAnimation = true; mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked( token); } } // If we're becoming visible, immediately change client visibility as well. there seem // to be some edge cases where we change our visibility but client visibility never gets // updated. // If we're becoming invisible, update the client visibility if we are not running an // animation. Otherwise, we'll update client visibility in onAnimationFinished. if (visible || !isAnimating()) { if (visible || !isAnimating(PARENTS)) { setClientVisible(visible); } final DisplayContent displayContent = getDisplayContent(); if (!displayContent.mClosingApps.contains(this) && !displayContent.mOpeningApps.contains(this)) { // The token is not closing nor opening, so even if there is an animation set, that Loading @@ -4137,14 +4130,40 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // can be synchronized with showing the next surface in the transition. if (!isVisible() && !delayed && !displayContent.mAppTransition.isTransitionSet()) { SurfaceControl.openTransaction(); for (int i = mChildren.size() - 1; i >= 0; i--) { mChildren.get(i).mWinAnimator.hide("immediately hidden"); } try { forAllWindows(win -> { win.mWinAnimator.hide("immediately hidden"); }, true); } finally { SurfaceControl.closeTransaction(); } } } return delayed; /** * Check if visibility of this {@link ActivityRecord} should be updated as part of an app * transition. * * <p class="note><strong>Note:</strong> If the visibility of this {@link ActivityRecord} is * already set to {@link #visible}, we don't need to update the visibility. So {@code false} is * returned.</p> * * @param visible {@code true} if this {@link ActivityRecord} should become visible, * {@code false} if this should become invisible. * @return {@code true} if visibility of this {@link ActivityRecord} should be updated, and * an app transition animation should be run. */ boolean shouldApplyAnimation(boolean visible) { // Allow for state update and animation to be applied if: // * token is transitioning visibility state // * or the token was marked as hidden and is exiting before we had a chance to play the // transition animation // * or this is an opening app and windows are being replaced // * or the token is the opening app and visible while opening task behind existing one. final DisplayContent displayContent = getDisplayContent(); return isVisible() != visible || (!isVisible() && mIsExiting) || (visible && forAllWindows(WindowState::waitingForReplacement, true)) || (visible && displayContent.mOpeningApps.contains(this) && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND); } /** Loading Loading @@ -5635,19 +5654,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return task != null ? task.isChangingAppTransition() : super.isChangingAppTransition(); } @Override boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) { if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) { ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: transition animation is disabled or skipped. " + "container=%s", this); cancelAnimation(); return false; } return super.applyAnimation(lp, transit, enter, isVoiceInteraction); } /** * Creates a layer to apply crop to an animation. */ Loading Loading @@ -5914,14 +5920,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A protected void onAnimationFinished() { super.onAnimationFinished(); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished"); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AR#onAnimationFinished"); mTransit = TRANSIT_UNSET; mTransitFlags = 0; mNeedsZBoost = false; mNeedsAnimationBoundsLayer = false; setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER, "AppWindowToken"); "ActivityRecord"); clearThumbnail(); setClientVisible(isVisible() || mVisibleRequested); Loading services/core/java/com/android/server/wm/AppTransitionController.java +77 −35 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/wm/WindowState.java +5 −14 Original line number Diff line number Diff line Loading @@ -1738,28 +1738,22 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP super.onMovedByResize(); } boolean onAppVisibilityChanged(boolean visible, boolean runningAppAnimation) { boolean changed = false; void onAppVisibilityChanged(boolean visible, boolean runningAppAnimation) { for (int i = mChildren.size() - 1; i >= 0; --i) { final WindowState c = mChildren.get(i); changed |= c.onAppVisibilityChanged(visible, runningAppAnimation); mChildren.get(i).onAppVisibilityChanged(visible, runningAppAnimation); } final boolean isVisibleNow = isVisibleNow(); if (mAttrs.type == TYPE_APPLICATION_STARTING) { // Starting window that's exiting will be removed when the animation finishes. // Mark all relevant flags for that onExitAnimationDone will proceed all the way // to actually remove it. if (!visible && isVisibleNow() && mActivityRecord.isAnimating(TRANSITION)) { if (!visible && isVisibleNow && mActivityRecord.isAnimating(TRANSITION)) { mAnimatingExit = true; mRemoveOnExit = true; mWindowRemovalAllowed = true; } return changed; } final boolean isVisibleNow = isVisibleNow(); if (visible != isVisibleNow) { } else if (visible != isVisibleNow) { // Run exit animation if: // 1. App visibility and WS visibility are different // 2. App is not running an animation Loading @@ -1773,11 +1767,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP accessibilityController.onWindowTransitionLocked(this, winTransit); } } changed = true; setDisplayLayoutNeeded(); } return changed; } boolean onSetAppExiting() { Loading services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +2 −3 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.TRANSIT_UNSET; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; Loading Loading @@ -303,8 +302,8 @@ public class AppWindowTokenTests extends WindowTestsBase { "closingWindow"); closingWindow.mAnimatingExit = true; closingWindow.mRemoveOnExit = true; closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET, true /* performLayout */, false /* isVoiceInteraction */); closingWindow.mActivityRecord.commitVisibility( false /* visible */, true /* performLayout */); // We pretended that we were running an exit animation, but that should have been cleared up // by changing visibility of ActivityRecord Loading Loading
data/etc/services.core.protolog.json +12 −18 Original line number Diff line number Diff line Loading @@ -79,12 +79,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "-1976550065": { "message": "commitVisibility: %s: visible=%b visibleRequested=%b", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "-1963461591": { "message": "Removing %s from %s", "level": "VERBOSE", Loading Loading @@ -283,6 +277,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "-1521427940": { "message": "commitVisibility: %s: visible=%b mVisibleRequested=%b", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "-1515151503": { "message": ">>> OPEN TRANSACTION removeReplacedWindows", "level": "INFO", Loading Loading @@ -697,12 +697,6 @@ "group": "WM_DEBUG_SCREEN_ON", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-633961578": { "message": "applyAnimation: transition animation is disabled or skipped. container=%s", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "-622997754": { "message": "postWindowRemoveCleanupLocked: %s", "level": "VERBOSE", Loading Loading @@ -1477,12 +1471,6 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, "841702299": { "message": "Changing app %s visible=%b performLayout=%b", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "845234215": { "message": "App is requesting an orientation, return %d for display id=%d", "level": "VERBOSE", Loading Loading @@ -1993,6 +1981,12 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, "1967975839": { "message": "Changing app %s visible=%b performLayout=%b", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/AppTransitionController.java" }, "1984470582": { "message": "Creating TaskScreenshotAnimatable: task: %s width: %d height: %d", "level": "DEBUG", Loading
services/core/java/com/android/server/wm/ActivityRecord.java +158 −152 Original line number Diff line number Diff line Loading @@ -547,7 +547,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults = new WindowState.UpdateReportedVisibilityResults(); private boolean mUseTransferredAnimation; boolean mUseTransferredAnimation; /** * @see #currentLaunchCanTurnScreenOn() Loading Loading @@ -2190,7 +2190,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** * Sets if this AWT is in the process of closing or entering PIP. * Sets if this {@link ActivityRecord} is in the process of closing or entering PIP. * {@link #mWillCloseOrEnterPip}} */ void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) { Loading @@ -2198,7 +2198,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** * Returns whether this AWT is considered closing. Conditions are either * Returns whether this {@link ActivityRecord} is considered closing. Conditions are either * 1. Is this app animating and was requested to be hidden * 2. App is delayed closing since it might enter PIP. */ Loading Loading @@ -3000,7 +3000,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this); boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction); commitVisibility(false /* visible */, true /* performLayout */); getDisplayContent().mOpeningApps.remove(this); getDisplayContent().mChangingApps.remove(this); Loading @@ -3008,6 +3008,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mWmService.mTaskSnapshotController.onAppRemoved(this); mStackSupervisor.getActivityMetricsLogger().notifyActivityRemoved(this); waitingToShow = false; boolean delayed = isAnimating(TRANSITION | CHILDREN); if (getDisplayContent().mClosingApps.contains(this)) { delayed = true; } else if (getDisplayContent().mAppTransition.isTransitionSet()) { Loading Loading @@ -3152,16 +3154,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A updateLetterboxSurface(child); } private boolean waitingForReplacement() { for (int i = mChildren.size() - 1; i >= 0; i--) { final WindowState candidate = mChildren.get(i); if (candidate.waitingForReplacement()) { return true; } } return false; } void onWindowReplacementTimeout() { for (int i = mChildren.size() - 1; i >= 0; --i) { (mChildren.get(i)).onWindowReplacementTimeout(); Loading Loading @@ -3417,7 +3409,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // before the non-exiting app tokens. So, we skip the exiting app tokens here. // TODO: Investigate if we need to continue to do this or if we can just process them // in-order. if (mIsExiting && !waitingForReplacement()) { if (mIsExiting && !forAllWindowsUnchecked(WindowState::waitingForReplacement, true)) { return false; } return forAllWindowsUnchecked(callback, traverseTopToBottom); Loading Loading @@ -3862,6 +3854,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } /** * Set visibility on this {@link ActivityRecord} * * <p class="note"><strong>Note: </strong>This function might not update the visibility of * this {@link ActivityRecord} immediately. In case we are preparing an app transition, we * delay changing the visibility of this {@link ActivityRecord} until we execute that * transition.</p> * * @param visible {@code true} if the {@link ActivityRecord} should become visible, otherwise * this should become invisible. */ void setVisibility(boolean visible) { if (getParent() == null) { Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " Loading Loading @@ -3998,62 +4001,45 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return; } commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction); commitVisibility(visible, true /* performLayout */); updateReportedVisibilityLocked(); } boolean commitVisibility(WindowManager.LayoutParams lp, boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) { boolean delayed = false; // Reset the state of mVisibleSetFromTransferredStartingWindow since visibility is actually // been set by the app now. mVisibleSetFromTransferredStartingWindow = false; // Allow for state changes and animation to be applied if: // * token is transitioning visibility state // * or the token was marked as hidden and is exiting before we had a chance to play the // transition animation // * or this is an opening app and windows are being replaced // * or the token is the opening app and visible while opening task behind existing one. final DisplayContent displayContent = getDisplayContent(); boolean visibilityChanged = false; if (isVisible() != visible || (!isVisible() && mIsExiting) || (visible && waitingForReplacement()) || (visible && displayContent.mOpeningApps.contains(this) && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) { final AccessibilityController accessibilityController = mWmService.mAccessibilityController; boolean changed = false; ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Changing app %s visible=%b performLayout=%b", this, isVisible(), performLayout); boolean runningAppAnimation = false; if (transit != WindowManager.TRANSIT_UNSET) { @Override boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) { if (mUseTransferredAnimation) { runningAppAnimation = isAnimating(); } else if (applyAnimation(lp, transit, visible, isVoiceInteraction)) { runningAppAnimation = true; return false; } delayed = runningAppAnimation; final WindowState window = findMainWindow(); if (window != null && accessibilityController != null) { accessibilityController.onAppWindowTransitionLocked(window, transit); return super.applyAnimation(lp, transit, enter, isVoiceInteraction); } changed = true; /** * Update visibility to this {@link ActivityRecord}. * * <p class="note"><strong>Note: </strong> Unlike {@link #setVisibility}, this immediately * updates the visibility without starting an app transition. Since this function may start * animation on {@link WindowState} depending on app transition animation status, an app * transition animation must be started before calling this function if necessary.</p> * * @param visible {@code true} if this {@link ActivityRecord} should become visible, otherwise * this should become invisible. * @param performLayout if {@code true}, perform surface placement after committing visibility. */ void commitVisibility(boolean visible, boolean performLayout) { // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually // been set by the app now. mVisibleSetFromTransferredStartingWindow = false; if (visible == isVisible()) { return; } final int windowsCount = mChildren.size(); for (int i = 0; i < windowsCount; i++) { final WindowState win = mChildren.get(i); changed |= win.onAppVisibilityChanged(visible, runningAppAnimation); mChildren.get(i).onAppVisibilityChanged(visible, isAnimating(PARENTS)); } setVisible(visible); mVisibleRequested = visible; visibilityChanged = true; if (!visible) { stopFreezingScreen(true, true); } else { Loading @@ -4063,17 +4049,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY); startingWindow.mLegacyPolicyVisibilityAfterAnim = false; } // We are becoming visible, so better freeze the screen with the windows that are // getting visible so we also wait for them. forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true); } ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "commitVisibility: %s: visible=%b visibleRequested=%b", this, "commitVisibility: %s: visible=%b mVisibleRequested=%b", this, isVisible(), mVisibleRequested); if (changed) { final DisplayContent displayContent = getDisplayContent(); displayContent.getInputMonitor().setUpdateInputWindowsNeededLw(); if (performLayout) { mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, Loading @@ -4081,36 +4064,46 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mWmService.mWindowPlacerLocked.performSurfacePlacement(); } displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/); } } mUseTransferredAnimation = false; delayed = isAnimating(CHILDREN); postApplyAnimation(visible); } /** * Post process after applying an app transition animation. * * <p class="note"><strong>Note: </strong> This function must be called after the animations * have been applied and {@link #commitVisibility}.</p> * * @param visible {@code true} if this {@link ActivityRecord} has become visible, otherwise * this has become invisible. */ private void postApplyAnimation(boolean visible) { final boolean delayed = isAnimating(PARENTS | CHILDREN); if (!delayed) { // We aren't animating anything, but exiting windows rely on the animation finished // callback being called in case the ActivityRecord was pretending to be animating, // We aren't delayed anything, but exiting windows rely on the animation finished // callback being called in case the ActivityRecord was pretending to be delayed, // which we might have done because we were in closing/opening apps list. onAnimationFinished(); } if (visibilityChanged) { if (visible && !delayed) { if (visible) { // The token was made immediately visible, there will be no entrance animation. // We need to inform the client the enter animation was finished. mEnteringAnimation = true; mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked( token); } } // If we're becoming visible, immediately change client visibility as well. there seem // to be some edge cases where we change our visibility but client visibility never gets // updated. // If we're becoming invisible, update the client visibility if we are not running an // animation. Otherwise, we'll update client visibility in onAnimationFinished. if (visible || !isAnimating()) { if (visible || !isAnimating(PARENTS)) { setClientVisible(visible); } final DisplayContent displayContent = getDisplayContent(); if (!displayContent.mClosingApps.contains(this) && !displayContent.mOpeningApps.contains(this)) { // The token is not closing nor opening, so even if there is an animation set, that Loading @@ -4137,14 +4130,40 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // can be synchronized with showing the next surface in the transition. if (!isVisible() && !delayed && !displayContent.mAppTransition.isTransitionSet()) { SurfaceControl.openTransaction(); for (int i = mChildren.size() - 1; i >= 0; i--) { mChildren.get(i).mWinAnimator.hide("immediately hidden"); } try { forAllWindows(win -> { win.mWinAnimator.hide("immediately hidden"); }, true); } finally { SurfaceControl.closeTransaction(); } } } return delayed; /** * Check if visibility of this {@link ActivityRecord} should be updated as part of an app * transition. * * <p class="note><strong>Note:</strong> If the visibility of this {@link ActivityRecord} is * already set to {@link #visible}, we don't need to update the visibility. So {@code false} is * returned.</p> * * @param visible {@code true} if this {@link ActivityRecord} should become visible, * {@code false} if this should become invisible. * @return {@code true} if visibility of this {@link ActivityRecord} should be updated, and * an app transition animation should be run. */ boolean shouldApplyAnimation(boolean visible) { // Allow for state update and animation to be applied if: // * token is transitioning visibility state // * or the token was marked as hidden and is exiting before we had a chance to play the // transition animation // * or this is an opening app and windows are being replaced // * or the token is the opening app and visible while opening task behind existing one. final DisplayContent displayContent = getDisplayContent(); return isVisible() != visible || (!isVisible() && mIsExiting) || (visible && forAllWindows(WindowState::waitingForReplacement, true)) || (visible && displayContent.mOpeningApps.contains(this) && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND); } /** Loading Loading @@ -5635,19 +5654,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return task != null ? task.isChangingAppTransition() : super.isChangingAppTransition(); } @Override boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) { if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) { ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: transition animation is disabled or skipped. " + "container=%s", this); cancelAnimation(); return false; } return super.applyAnimation(lp, transit, enter, isVoiceInteraction); } /** * Creates a layer to apply crop to an animation. */ Loading Loading @@ -5914,14 +5920,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A protected void onAnimationFinished() { super.onAnimationFinished(); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished"); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AR#onAnimationFinished"); mTransit = TRANSIT_UNSET; mTransitFlags = 0; mNeedsZBoost = false; mNeedsAnimationBoundsLayer = false; setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER, "AppWindowToken"); "ActivityRecord"); clearThumbnail(); setClientVisible(isVisible() || mVisibleRequested); Loading
services/core/java/com/android/server/wm/AppTransitionController.java +77 −35 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/wm/WindowState.java +5 −14 Original line number Diff line number Diff line Loading @@ -1738,28 +1738,22 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP super.onMovedByResize(); } boolean onAppVisibilityChanged(boolean visible, boolean runningAppAnimation) { boolean changed = false; void onAppVisibilityChanged(boolean visible, boolean runningAppAnimation) { for (int i = mChildren.size() - 1; i >= 0; --i) { final WindowState c = mChildren.get(i); changed |= c.onAppVisibilityChanged(visible, runningAppAnimation); mChildren.get(i).onAppVisibilityChanged(visible, runningAppAnimation); } final boolean isVisibleNow = isVisibleNow(); if (mAttrs.type == TYPE_APPLICATION_STARTING) { // Starting window that's exiting will be removed when the animation finishes. // Mark all relevant flags for that onExitAnimationDone will proceed all the way // to actually remove it. if (!visible && isVisibleNow() && mActivityRecord.isAnimating(TRANSITION)) { if (!visible && isVisibleNow && mActivityRecord.isAnimating(TRANSITION)) { mAnimatingExit = true; mRemoveOnExit = true; mWindowRemovalAllowed = true; } return changed; } final boolean isVisibleNow = isVisibleNow(); if (visible != isVisibleNow) { } else if (visible != isVisibleNow) { // Run exit animation if: // 1. App visibility and WS visibility are different // 2. App is not running an animation Loading @@ -1773,11 +1767,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP accessibilityController.onWindowTransitionLocked(this, winTransit); } } changed = true; setDisplayLayoutNeeded(); } return changed; } boolean onSetAppExiting() { Loading
services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +2 −3 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.TRANSIT_UNSET; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; Loading Loading @@ -303,8 +302,8 @@ public class AppWindowTokenTests extends WindowTestsBase { "closingWindow"); closingWindow.mAnimatingExit = true; closingWindow.mRemoveOnExit = true; closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET, true /* performLayout */, false /* isVoiceInteraction */); closingWindow.mActivityRecord.commitVisibility( false /* visible */, true /* performLayout */); // We pretended that we were running an exit animation, but that should have been cleared up // by changing visibility of ActivityRecord Loading