Merge "Separate animation applying logic from commitVisibility"
This commit is contained in:
@@ -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",
|
||||
@@ -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",
|
||||
@@ -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",
|
||||
@@ -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",
|
||||
@@ -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",
|
||||
|
||||
@@ -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()
|
||||
@@ -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) {
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -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);
|
||||
@@ -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()) {
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
@@ -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: "
|
||||
@@ -3998,153 +4001,169 @@ 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) {
|
||||
@Override
|
||||
boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
|
||||
boolean isVoiceInteraction) {
|
||||
if (mUseTransferredAnimation) {
|
||||
return false;
|
||||
}
|
||||
return super.applyAnimation(lp, transit, enter, isVoiceInteraction);
|
||||
}
|
||||
|
||||
boolean delayed = false;
|
||||
// Reset the state of mVisibleSetFromTransferredStartingWindow since visibility is actually
|
||||
/**
|
||||
* 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;
|
||||
|
||||
// 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) {
|
||||
if (mUseTransferredAnimation) {
|
||||
runningAppAnimation = isAnimating();
|
||||
} else if (applyAnimation(lp, transit, visible, isVoiceInteraction)) {
|
||||
runningAppAnimation = true;
|
||||
}
|
||||
delayed = runningAppAnimation;
|
||||
final WindowState window = findMainWindow();
|
||||
if (window != null && accessibilityController != null) {
|
||||
accessibilityController.onAppWindowTransitionLocked(window, transit);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
final int windowsCount = mChildren.size();
|
||||
for (int i = 0; i < windowsCount; i++) {
|
||||
final WindowState win = mChildren.get(i);
|
||||
changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
|
||||
}
|
||||
|
||||
setVisible(visible);
|
||||
mVisibleRequested = visible;
|
||||
visibilityChanged = true;
|
||||
if (!visible) {
|
||||
stopFreezingScreen(true, true);
|
||||
} else {
|
||||
// If we are being set visible, and the starting window is not yet displayed,
|
||||
// then make sure it doesn't get displayed.
|
||||
if (startingWindow != null && !startingWindow.isDrawnLw()) {
|
||||
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,
|
||||
isVisible(), mVisibleRequested);
|
||||
|
||||
if (changed) {
|
||||
displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
|
||||
if (performLayout) {
|
||||
mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
|
||||
false /*updateInputWindows*/);
|
||||
mWmService.mWindowPlacerLocked.performSurfacePlacement();
|
||||
}
|
||||
displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
|
||||
}
|
||||
if (visible == isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int windowsCount = mChildren.size();
|
||||
for (int i = 0; i < windowsCount; i++) {
|
||||
mChildren.get(i).onAppVisibilityChanged(visible, isAnimating(PARENTS));
|
||||
}
|
||||
setVisible(visible);
|
||||
mVisibleRequested = visible;
|
||||
if (!visible) {
|
||||
stopFreezingScreen(true, true);
|
||||
} else {
|
||||
// If we are being set visible, and the starting window is not yet displayed,
|
||||
// then make sure it doesn't get displayed.
|
||||
if (startingWindow != null && !startingWindow.isDrawnLw()) {
|
||||
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 mVisibleRequested=%b", this,
|
||||
isVisible(), mVisibleRequested);
|
||||
final DisplayContent displayContent = getDisplayContent();
|
||||
displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
|
||||
if (performLayout) {
|
||||
mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
|
||||
false /*updateInputWindows*/);
|
||||
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()) {
|
||||
setClientVisible(visible);
|
||||
}
|
||||
// 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(PARENTS)) {
|
||||
setClientVisible(visible);
|
||||
}
|
||||
|
||||
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
|
||||
// doesn't mean that it goes through the normal app transition cycle so we have
|
||||
// to inform the docked controller about visibility change.
|
||||
// TODO(multi-display): notify docked divider on all displays where visibility was
|
||||
// affected.
|
||||
displayContent.getDockedDividerController().notifyAppVisibilityChanged();
|
||||
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
|
||||
// doesn't mean that it goes through the normal app transition cycle so we have
|
||||
// to inform the docked controller about visibility change.
|
||||
// TODO(multi-display): notify docked divider on all displays where visibility was
|
||||
// affected.
|
||||
displayContent.getDockedDividerController().notifyAppVisibilityChanged();
|
||||
|
||||
// Take the screenshot before possibly hiding the WSA, otherwise the screenshot
|
||||
// will not be taken.
|
||||
mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
|
||||
}
|
||||
// Take the screenshot before possibly hiding the WSA, otherwise the screenshot
|
||||
// will not be taken.
|
||||
mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
|
||||
}
|
||||
|
||||
// If we are hidden but there is no delay needed we immediately
|
||||
// apply the Surface transaction so that the ActivityManager
|
||||
// can have some guarantee on the Surface state following
|
||||
// setting the visibility. This captures cases like dismissing
|
||||
// the docked or pinned stack where there is no app transition.
|
||||
//
|
||||
// In the case of a "Null" animation, there will be
|
||||
// no animation but there will still be a transition set.
|
||||
// We still need to delay hiding the surface such that it
|
||||
// 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");
|
||||
}
|
||||
// If we are hidden but there is no delay needed we immediately
|
||||
// apply the Surface transaction so that the ActivityManager
|
||||
// can have some guarantee on the Surface state following
|
||||
// setting the visibility. This captures cases like dismissing
|
||||
// the docked or pinned stack where there is no app transition.
|
||||
//
|
||||
// In the case of a "Null" animation, there will be
|
||||
// no animation but there will still be a transition set.
|
||||
// We still need to delay hiding the surface such that it
|
||||
// can be synchronized with showing the next surface in the transition.
|
||||
if (!isVisible() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
|
||||
SurfaceControl.openTransaction();
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -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);
|
||||
|
||||
@@ -48,6 +48,8 @@ import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_S
|
||||
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
|
||||
import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
|
||||
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
|
||||
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
@@ -61,6 +63,7 @@ import android.view.RemoteAnimationAdapter;
|
||||
import android.view.RemoteAnimationDefinition;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.view.WindowManager.TransitionType;
|
||||
import android.view.animation.Animation;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -177,9 +180,15 @@ public class AppTransitionController {
|
||||
final int layoutRedo;
|
||||
mService.mSurfaceAnimationRunner.deferStartingAnimations();
|
||||
try {
|
||||
handleClosingApps(transit, animLp, voiceInteraction);
|
||||
handleOpeningApps(transit, animLp, voiceInteraction);
|
||||
handleChangingApps(transit, animLp, voiceInteraction);
|
||||
// TODO: Apply an app transition animation on TaskStack instead of ActivityRecord when
|
||||
// appropriate.
|
||||
applyAnimations(mDisplayContent.mClosingApps, transit, false /* visible */,
|
||||
animLp, voiceInteraction);
|
||||
applyAnimations(mDisplayContent.mOpeningApps, transit, true /* visible */,
|
||||
animLp, voiceInteraction);
|
||||
handleClosingApps();
|
||||
handleOpeningApps();
|
||||
handleChangingApps(transit);
|
||||
|
||||
appTransition.setLastAppTransition(transit, topOpeningApp,
|
||||
topClosingApp, topChangingApp);
|
||||
@@ -227,8 +236,8 @@ public class AppTransitionController {
|
||||
return mainWindow != null ? mainWindow.mAttrs : null;
|
||||
}
|
||||
|
||||
RemoteAnimationAdapter getRemoteAnimationOverride(ActivityRecord animLpActivity, int transit,
|
||||
ArraySet<Integer> activityTypes) {
|
||||
RemoteAnimationAdapter getRemoteAnimationOverride(ActivityRecord animLpActivity,
|
||||
@TransitionType int transit, ArraySet<Integer> activityTypes) {
|
||||
final RemoteAnimationDefinition definition = animLpActivity.getRemoteAnimationDefinition();
|
||||
if (definition != null) {
|
||||
final RemoteAnimationAdapter adapter = definition.getAdapter(transit, activityTypes);
|
||||
@@ -246,8 +255,8 @@ public class AppTransitionController {
|
||||
* Overrides the pending transition with the remote animation defined for the transition in the
|
||||
* set of defined remote animations in the app window token.
|
||||
*/
|
||||
private void overrideWithRemoteAnimationIfSet(ActivityRecord animLpActivity, int transit,
|
||||
ArraySet<Integer> activityTypes) {
|
||||
private void overrideWithRemoteAnimationIfSet(ActivityRecord animLpActivity,
|
||||
@TransitionType int transit, ArraySet<Integer> activityTypes) {
|
||||
if (transit == TRANSIT_CRASHING_ACTIVITY_CLOSE) {
|
||||
// The crash transition has higher priority than any involved remote animations.
|
||||
return;
|
||||
@@ -266,7 +275,7 @@ public class AppTransitionController {
|
||||
/**
|
||||
* @return The window token that determines the animation theme.
|
||||
*/
|
||||
private ActivityRecord findAnimLayoutParamsToken(@WindowManager.TransitionType int transit,
|
||||
private ActivityRecord findAnimLayoutParamsToken(@TransitionType int transit,
|
||||
ArraySet<Integer> activityTypes) {
|
||||
ActivityRecord result;
|
||||
final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
|
||||
@@ -340,26 +349,60 @@ public class AppTransitionController {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void handleOpeningApps(int transit, LayoutParams animLp, boolean voiceInteraction) {
|
||||
/**
|
||||
* Apply an app transition animation on a set of {@link ActivityRecord}
|
||||
*
|
||||
* @param apps The list of apps to which an app transition animation applies.
|
||||
* @param transit The current transition type.
|
||||
* @param visible {@code true} if the apps becomes visible, {@code false} if the apps becomes
|
||||
* invisible.
|
||||
* @param animLp Layout parameters in which an app transition animation runs.
|
||||
* @param voiceInteraction {@code true} if one of the apps in this transition belongs to a voice
|
||||
* interaction session driving task.
|
||||
*/
|
||||
private void applyAnimations(ArraySet<ActivityRecord> apps, @TransitionType int transit,
|
||||
boolean visible, LayoutParams animLp, boolean voiceInteraction) {
|
||||
final int appsCount = apps.size();
|
||||
for (int i = 0; i < appsCount; i++) {
|
||||
final ActivityRecord app = apps.valueAt(i);
|
||||
if (transit != WindowManager.TRANSIT_UNSET && app.shouldApplyAnimation(visible)) {
|
||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Changing app %s visible=%b performLayout=%b",
|
||||
app, app.isVisible(), false);
|
||||
if (!app.mUseTransferredAnimation) {
|
||||
app.applyAnimation(animLp, transit, visible, voiceInteraction);
|
||||
}
|
||||
final WindowState window = app.findMainWindow();
|
||||
final AccessibilityController accessibilityController =
|
||||
app.mWmService.mAccessibilityController;
|
||||
if (window != null && accessibilityController != null) {
|
||||
accessibilityController.onAppWindowTransitionLocked(window, transit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleOpeningApps() {
|
||||
final ArraySet<ActivityRecord> openingApps = mDisplayContent.mOpeningApps;
|
||||
final int appsCount = openingApps.size();
|
||||
for (int i = 0; i < appsCount; i++) {
|
||||
ActivityRecord wtoken = openingApps.valueAt(i);
|
||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now opening app %s", wtoken);
|
||||
|
||||
if (!wtoken.commitVisibility(animLp, true, transit, false, voiceInteraction)) {
|
||||
for (int i = 0; i < appsCount; i++) {
|
||||
final ActivityRecord app = openingApps.valueAt(i);
|
||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now opening app %s", app);
|
||||
|
||||
app.commitVisibility(true /* visible */, false /* performLayout */);
|
||||
if (!app.isAnimating(PARENTS | CHILDREN)) {
|
||||
// This token isn't going to be animating. Add it to the list of tokens to
|
||||
// be notified of app transition complete since the notification will not be
|
||||
// sent be the app window animator.
|
||||
mDisplayContent.mNoAnimationNotifyOnTransitionFinished.add(wtoken.token);
|
||||
mDisplayContent.mNoAnimationNotifyOnTransitionFinished.add(app.token);
|
||||
}
|
||||
wtoken.updateReportedVisibilityLocked();
|
||||
wtoken.waitingToShow = false;
|
||||
app.updateReportedVisibilityLocked();
|
||||
app.waitingToShow = false;
|
||||
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
|
||||
">>> OPEN TRANSACTION handleAppTransitionReady()");
|
||||
mService.openSurfaceTransaction();
|
||||
try {
|
||||
wtoken.showAllWindowsLocked();
|
||||
app.showAllWindowsLocked();
|
||||
} finally {
|
||||
mService.closeSurfaceTransaction("handleAppTransitionReady");
|
||||
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
|
||||
@@ -367,41 +410,40 @@ public class AppTransitionController {
|
||||
}
|
||||
|
||||
if (mDisplayContent.mAppTransition.isNextAppTransitionThumbnailUp()) {
|
||||
wtoken.attachThumbnailAnimation();
|
||||
app.attachThumbnailAnimation();
|
||||
} else if (mDisplayContent.mAppTransition.isNextAppTransitionOpenCrossProfileApps()) {
|
||||
wtoken.attachCrossProfileAppsThumbnailAnimation();
|
||||
app.attachCrossProfileAppsThumbnailAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleClosingApps(int transit, LayoutParams animLp, boolean voiceInteraction) {
|
||||
private void handleClosingApps() {
|
||||
final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
|
||||
final int appsCount = closingApps.size();
|
||||
for (int i = 0; i < appsCount; i++) {
|
||||
ActivityRecord wtoken = closingApps.valueAt(i);
|
||||
|
||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now closing app %s", wtoken);
|
||||
// TODO: Do we need to add to mNoAnimationNotifyOnTransitionFinished like above if not
|
||||
// animating?
|
||||
wtoken.commitVisibility(animLp, false, transit, false, voiceInteraction);
|
||||
wtoken.updateReportedVisibilityLocked();
|
||||
for (int i = 0; i < appsCount; i++) {
|
||||
final ActivityRecord app = closingApps.valueAt(i);
|
||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now closing app %s", app);
|
||||
|
||||
app.commitVisibility(false /* visible */, false /* performLayout */);
|
||||
app.updateReportedVisibilityLocked();
|
||||
// Force the allDrawn flag, because we want to start
|
||||
// this guy's animations regardless of whether it's
|
||||
// gotten drawn.
|
||||
wtoken.allDrawn = true;
|
||||
app.allDrawn = true;
|
||||
// Ensure that apps that are mid-starting are also scheduled to have their
|
||||
// starting windows removed after the animation is complete
|
||||
if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit) {
|
||||
wtoken.removeStartingWindow();
|
||||
if (app.startingWindow != null && !app.startingWindow.mAnimatingExit) {
|
||||
app.removeStartingWindow();
|
||||
}
|
||||
|
||||
if (mDisplayContent.mAppTransition.isNextAppTransitionThumbnailDown()) {
|
||||
wtoken.attachThumbnailAnimation();
|
||||
app.attachThumbnailAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleChangingApps(int transit, LayoutParams animLp, boolean voiceInteraction) {
|
||||
private void handleChangingApps(@TransitionType int transit) {
|
||||
final ArraySet<ActivityRecord> apps = mDisplayContent.mChangingApps;
|
||||
final int appsCount = apps.size();
|
||||
for (int i = 0; i < appsCount; i++) {
|
||||
@@ -419,7 +461,7 @@ public class AppTransitionController {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleNonAppWindowsInTransition(int transit, int flags) {
|
||||
private void handleNonAppWindowsInTransition(@TransitionType int transit, int flags) {
|
||||
if (transit == TRANSIT_KEYGUARD_GOING_AWAY) {
|
||||
if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0
|
||||
&& (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0
|
||||
@@ -510,8 +552,8 @@ public class AppTransitionController {
|
||||
return true;
|
||||
}
|
||||
|
||||
private int maybeUpdateTransitToWallpaper(int transit, boolean openingAppHasWallpaper,
|
||||
boolean closingAppHasWallpaper) {
|
||||
private int maybeUpdateTransitToWallpaper(@TransitionType int transit,
|
||||
boolean openingAppHasWallpaper, boolean closingAppHasWallpaper) {
|
||||
// Given no app transition pass it through instead of a wallpaper transition.
|
||||
// Never convert the crashing transition.
|
||||
// Never update the transition for the wallpaper if we are just docking from recents
|
||||
@@ -604,7 +646,7 @@ public class AppTransitionController {
|
||||
* situation.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
int maybeUpdateTransitToTranslucentAnim(int transit) {
|
||||
int maybeUpdateTransitToTranslucentAnim(@TransitionType int transit) {
|
||||
if (AppTransition.isChangeTransit(transit)) {
|
||||
// There's no special animation to handle change animations with translucent apps
|
||||
return transit;
|
||||
@@ -644,7 +686,7 @@ public class AppTransitionController {
|
||||
* to determine whether animations should be clipped to the task bounds instead of stack bounds.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean isTransitWithinTask(int transit, Task task) {
|
||||
boolean isTransitWithinTask(@TransitionType int transit, Task task) {
|
||||
if (task == null
|
||||
|| !mDisplayContent.mChangingApps.isEmpty()) {
|
||||
// if there is no task, then we can't constrain to the task.
|
||||
|
||||
@@ -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
|
||||
@@ -1773,11 +1767,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
accessibilityController.onWindowTransitionLocked(this, winTransit);
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
setDisplayLayoutNeeded();
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
boolean onSetAppExiting() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.android.server.wm;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
|
||||
import static android.view.WindowManager.TRANSIT_UNSET;
|
||||
|
||||
import static com.android.server.wm.TaskSnapshotController.SNAPSHOT_MODE_APP_THEME;
|
||||
import static com.android.server.wm.TaskSnapshotController.SNAPSHOT_MODE_REAL;
|
||||
@@ -50,8 +49,8 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
|
||||
public void testGetClosingApps_closing() {
|
||||
final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
|
||||
"closingWindow");
|
||||
closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
|
||||
true /* performLayout */, false /* isVoiceInteraction */);
|
||||
closingWindow.mActivityRecord.commitVisibility(
|
||||
false /* visible */, true /* performLayout */);
|
||||
final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
|
||||
closingApps.add(closingWindow.mActivityRecord);
|
||||
final ArraySet<Task> closingTasks = new ArraySet<>();
|
||||
@@ -66,10 +65,10 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
|
||||
"closingWindow");
|
||||
final WindowState openingWindow = createAppWindow(closingWindow.getTask(),
|
||||
FIRST_APPLICATION_WINDOW, "openingWindow");
|
||||
closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
|
||||
true /* performLayout */, false /* isVoiceInteraction */);
|
||||
openingWindow.mActivityRecord.commitVisibility(null, true /* visible */, TRANSIT_UNSET,
|
||||
true /* performLayout */, false /* isVoiceInteraction */);
|
||||
closingWindow.mActivityRecord.commitVisibility(
|
||||
false /* visible */, true /* performLayout */);
|
||||
openingWindow.mActivityRecord.commitVisibility(
|
||||
true /* visible */, true /* performLayout */);
|
||||
final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
|
||||
closingApps.add(closingWindow.mActivityRecord);
|
||||
final ArraySet<Task> closingTasks = new ArraySet<>();
|
||||
@@ -81,8 +80,8 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
|
||||
public void testGetClosingApps_skipClosingAppsSnapshotTasks() {
|
||||
final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
|
||||
"closingWindow");
|
||||
closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
|
||||
true /* performLayout */, false /* isVoiceInteraction */);
|
||||
closingWindow.mActivityRecord.commitVisibility(
|
||||
false /* visible */, true /* performLayout */);
|
||||
final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
|
||||
closingApps.add(closingWindow.mActivityRecord);
|
||||
final ArraySet<Task> closingTasks = new ArraySet<>();
|
||||
|
||||
Reference in New Issue
Block a user