Merge "Separate animation applying logic from commitVisibility"

This commit is contained in:
Issei Suzuki
2019-12-12 05:44:26 +00:00
committed by Android (Google) Code Review
6 changed files with 263 additions and 232 deletions

View File

@@ -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",

View File

@@ -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);

View File

@@ -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.

View File

@@ -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() {

View File

@@ -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

View File

@@ -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<>();