Lock free app animations (2/n): Use SurfaceAninimator
This is the main CL that switches over from using the legacy animation system to using the new SurfaceAnimator for app window animations. Also moves applyAnimationLocked to AppWindowToken. AppWindowAnimator still has a bunch of state that needs to be moved into AppWindowToken in future CL's. Test: go/wm-smoke Bug: 64674361 Change-Id: Ifc83cbac281ce0654ecd8a1c2ca9c24a4d87c1d1
This commit is contained in:
@@ -2126,14 +2126,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
|
||||
@Override
|
||||
public int onAppTransitionStartingLocked(int transit, IBinder openToken,
|
||||
IBinder closeToken,
|
||||
Animation openAnimation, Animation closeAnimation) {
|
||||
return handleStartTransitionForKeyguardLw(transit, openAnimation);
|
||||
IBinder closeToken, long duration, long statusBarAnimationStartTime,
|
||||
long statusBarAnimationDuration) {
|
||||
return handleStartTransitionForKeyguardLw(transit, duration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppTransitionCancelledLocked(int transit) {
|
||||
handleStartTransitionForKeyguardLw(transit, null /* transit */);
|
||||
handleStartTransitionForKeyguardLw(transit, 0 /* duration */);
|
||||
}
|
||||
});
|
||||
mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
|
||||
@@ -3989,7 +3989,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
private int handleStartTransitionForKeyguardLw(int transit, @Nullable Animation anim) {
|
||||
private int handleStartTransitionForKeyguardLw(int transit, long duration) {
|
||||
if (mKeyguardOccludedChanged) {
|
||||
if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
|
||||
+ mPendingKeyguardOccluded);
|
||||
@@ -4000,13 +4000,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
}
|
||||
if (AppTransition.isKeyguardGoingAwayTransit(transit)) {
|
||||
if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
|
||||
final long startTime = anim != null
|
||||
? SystemClock.uptimeMillis() + anim.getStartOffset()
|
||||
: SystemClock.uptimeMillis();
|
||||
final long duration = anim != null
|
||||
? anim.getDuration()
|
||||
: 0;
|
||||
startKeyguardExitAnimation(startTime, duration);
|
||||
startKeyguardExitAnimation(SystemClock.uptimeMillis(), duration);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ import com.android.server.statusbar.StatusBarManagerInternal;
|
||||
*/
|
||||
public class StatusBarController extends BarController {
|
||||
|
||||
private static final long TRANSITION_DURATION = 120L;
|
||||
|
||||
private final AppTransitionListener mAppTransitionListener
|
||||
= new AppTransitionListener() {
|
||||
|
||||
@@ -57,17 +55,15 @@ public class StatusBarController extends BarController {
|
||||
|
||||
@Override
|
||||
public int onAppTransitionStartingLocked(int transit, IBinder openToken,
|
||||
IBinder closeToken, final Animation openAnimation, final Animation closeAnimation) {
|
||||
IBinder closeToken, long duration, long statusBarAnimationStartTime,
|
||||
long statusBarAnimationDuration) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
StatusBarManagerInternal statusbar = getStatusBarInternal();
|
||||
if (statusbar != null) {
|
||||
long startTime = calculateStatusBarTransitionStartTime(openAnimation,
|
||||
closeAnimation);
|
||||
long duration = closeAnimation != null || openAnimation != null
|
||||
? TRANSITION_DURATION : 0;
|
||||
statusbar.appTransitionStarting(startTime, duration);
|
||||
statusbar.appTransitionStarting(statusBarAnimationStartTime,
|
||||
statusBarAnimationDuration);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -128,72 +124,4 @@ public class StatusBarController extends BarController {
|
||||
public AppTransitionListener getAppTransitionListener() {
|
||||
return mAppTransitionListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given app transition with {@code openAnimation} and {@code closeAnimation}, this
|
||||
* calculates the timings for the corresponding status bar transition.
|
||||
*
|
||||
* @return the desired start time of the status bar transition, in uptime millis
|
||||
*/
|
||||
private static long calculateStatusBarTransitionStartTime(Animation openAnimation,
|
||||
Animation closeAnimation) {
|
||||
if (openAnimation != null && closeAnimation != null) {
|
||||
TranslateAnimation openTranslateAnimation = findTranslateAnimation(openAnimation);
|
||||
TranslateAnimation closeTranslateAnimation = findTranslateAnimation(closeAnimation);
|
||||
if (openTranslateAnimation != null) {
|
||||
|
||||
// Some interpolators are extremely quickly mostly finished, but not completely. For
|
||||
// our purposes, we need to find the fraction for which ther interpolator is mostly
|
||||
// there, and use that value for the calculation.
|
||||
float t = findAlmostThereFraction(openTranslateAnimation.getInterpolator());
|
||||
return SystemClock.uptimeMillis()
|
||||
+ openTranslateAnimation.getStartOffset()
|
||||
+ (long)(openTranslateAnimation.getDuration()*t) - TRANSITION_DURATION;
|
||||
} else if (closeTranslateAnimation != null) {
|
||||
return SystemClock.uptimeMillis();
|
||||
} else {
|
||||
return SystemClock.uptimeMillis();
|
||||
}
|
||||
} else {
|
||||
return SystemClock.uptimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to find a {@link TranslateAnimation} inside the {@code animation}.
|
||||
*
|
||||
* @return the found animation, {@code null} otherwise
|
||||
*/
|
||||
private static TranslateAnimation findTranslateAnimation(Animation animation) {
|
||||
if (animation instanceof TranslateAnimation) {
|
||||
return (TranslateAnimation) animation;
|
||||
} else if (animation instanceof AnimationSet) {
|
||||
AnimationSet set = (AnimationSet) animation;
|
||||
for (int i = 0; i < set.getAnimations().size(); i++) {
|
||||
Animation a = set.getAnimations().get(i);
|
||||
if (a instanceof TranslateAnimation) {
|
||||
return (TranslateAnimation) a;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binary searches for a {@code t} such that there exists a {@code -0.01 < eps < 0.01} for which
|
||||
* {@code interpolator(t + eps) > 0.99}.
|
||||
*/
|
||||
private static float findAlmostThereFraction(Interpolator interpolator) {
|
||||
float val = 0.5f;
|
||||
float adj = 0.25f;
|
||||
while (adj >= 0.01f) {
|
||||
if (interpolator.getInterpolation(val) < 0.99f) {
|
||||
val += adj;
|
||||
} else {
|
||||
val -= adj;
|
||||
}
|
||||
adj /= 2;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
||||
*/
|
||||
interface AnimationAdapter {
|
||||
|
||||
long STATUS_BAR_TRANSITION_DURATION = 120L;
|
||||
|
||||
/**
|
||||
* @return Whether we should detach the wallpaper during the animation.
|
||||
* @see Animation#setDetachWallpaper
|
||||
@@ -66,4 +68,13 @@ interface AnimationAdapter {
|
||||
* @return The approximate duration of the animation, in milliseconds.
|
||||
*/
|
||||
long getDurationHint();
|
||||
|
||||
/**
|
||||
* If this animation is run as an app opening animation, this calculates the start time for all
|
||||
* status bar transitions that happen as part of the app opening animation, which will be
|
||||
* forwarded to SystemUI.
|
||||
*
|
||||
* @return the desired start time of the status bar transition, in uptime millis
|
||||
*/
|
||||
long getStatusBarTransitionsStartTime();
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpe
|
||||
import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
|
||||
import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation;
|
||||
import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
|
||||
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
@@ -63,6 +62,7 @@ import android.os.Debug;
|
||||
import android.os.IBinder;
|
||||
import android.os.IRemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArraySet;
|
||||
@@ -415,17 +415,23 @@ public class AppTransition implements Dump {
|
||||
* @return bit-map of WindowManagerPolicy#FINISH_LAYOUT_REDO_* to indicate whether another
|
||||
* layout pass needs to be done
|
||||
*/
|
||||
int goodToGo(int transit, AppWindowAnimator topOpeningAppAnimator,
|
||||
AppWindowAnimator topClosingAppAnimator, ArraySet<AppWindowToken> openingApps,
|
||||
int goodToGo(int transit, AppWindowToken topOpeningApp,
|
||||
AppWindowToken topClosingApp, ArraySet<AppWindowToken> openingApps,
|
||||
ArraySet<AppWindowToken> closingApps) {
|
||||
mNextAppTransition = TRANSIT_UNSET;
|
||||
mNextAppTransitionFlags = 0;
|
||||
setAppTransitionState(APP_STATE_RUNNING);
|
||||
final AnimationAdapter topOpeningAnim = topOpeningApp != null
|
||||
? topOpeningApp.getAnimation()
|
||||
: null;
|
||||
int redoLayout = notifyAppTransitionStartingLocked(transit,
|
||||
topOpeningAppAnimator != null ? topOpeningAppAnimator.mAppToken.token : null,
|
||||
topClosingAppAnimator != null ? topClosingAppAnimator.mAppToken.token : null,
|
||||
topOpeningAppAnimator != null ? topOpeningAppAnimator.animation : null,
|
||||
topClosingAppAnimator != null ? topClosingAppAnimator.animation : null);
|
||||
topOpeningApp != null ? topOpeningApp.token : null,
|
||||
topClosingApp != null ? topClosingApp.token : null,
|
||||
topOpeningAnim != null ? topOpeningAnim.getDurationHint() : 0,
|
||||
topOpeningAnim != null
|
||||
? topOpeningAnim.getStatusBarTransitionsStartTime()
|
||||
: SystemClock.uptimeMillis(),
|
||||
AnimationAdapter.STATUS_BAR_TRANSITION_DURATION);
|
||||
mService.getDefaultDisplayContentLocked().getDockedDividerController()
|
||||
.notifyAppTransitionStarting(openingApps, transit);
|
||||
|
||||
@@ -433,8 +439,8 @@ public class AppTransition implements Dump {
|
||||
// ended it already then we don't need to wait.
|
||||
if (transit == TRANSIT_DOCK_TASK_FROM_RECENTS && !mProlongedAnimationsEnded) {
|
||||
for (int i = openingApps.size() - 1; i >= 0; i--) {
|
||||
final AppWindowAnimator appAnimator = openingApps.valueAt(i).mAppAnimator;
|
||||
appAnimator.startProlongAnimation(PROLONG_ANIMATION_AT_START);
|
||||
final AppWindowToken app = openingApps.valueAt(i);
|
||||
app.startDelayingAnimationStart();
|
||||
}
|
||||
}
|
||||
return redoLayout;
|
||||
@@ -504,11 +510,12 @@ public class AppTransition implements Dump {
|
||||
}
|
||||
|
||||
private int notifyAppTransitionStartingLocked(int transit, IBinder openToken,
|
||||
IBinder closeToken, Animation openAnimation, Animation closeAnimation) {
|
||||
IBinder closeToken, long duration, long statusBarAnimationStartTime,
|
||||
long statusBarAnimationDuration) {
|
||||
int redoLayout = 0;
|
||||
for (int i = 0; i < mListeners.size(); i++) {
|
||||
redoLayout |= mListeners.get(i).onAppTransitionStartingLocked(transit, openToken,
|
||||
closeToken, openAnimation, closeAnimation);
|
||||
closeToken, duration, statusBarAnimationStartTime, statusBarAnimationDuration);
|
||||
}
|
||||
return redoLayout;
|
||||
}
|
||||
@@ -1885,9 +1892,6 @@ public class AppTransition implements Dump {
|
||||
mNextAppTransitionFutureCallback, null /* finishedCallback */,
|
||||
mNextAppTransitionScaleUp);
|
||||
mNextAppTransitionFutureCallback = null;
|
||||
if (specs != null) {
|
||||
mService.prolongAnimationsFromSpecs(specs, mNextAppTransitionScaleUp);
|
||||
}
|
||||
}
|
||||
mService.requestTraversal();
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -11,51 +11,25 @@
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
|
||||
import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
|
||||
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
|
||||
|
||||
import android.graphics.Matrix;
|
||||
import android.util.Slog;
|
||||
import android.util.TimeUtils;
|
||||
import android.view.Choreographer;
|
||||
import android.view.Display;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.Transformation;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
// TODO: Move all remaining fields to AppWindowToken and remove this class.
|
||||
public class AppWindowAnimator {
|
||||
static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowAnimator" : TAG_WM;
|
||||
|
||||
private static final int PROLONG_ANIMATION_DISABLED = 0;
|
||||
static final int PROLONG_ANIMATION_AT_END = 1;
|
||||
static final int PROLONG_ANIMATION_AT_START = 2;
|
||||
|
||||
final AppWindowToken mAppToken;
|
||||
final WindowManagerService mService;
|
||||
final WindowAnimator mAnimator;
|
||||
|
||||
boolean animating;
|
||||
boolean wasAnimating;
|
||||
Animation animation;
|
||||
boolean hasTransformation;
|
||||
final Transformation transformation = new Transformation();
|
||||
|
||||
// Have we been asked to have this token keep the screen frozen?
|
||||
// Protect with mAnimator.
|
||||
boolean freezingScreen;
|
||||
@@ -78,400 +52,11 @@ public class AppWindowAnimator {
|
||||
// requires that the duration of the two animations are the same.
|
||||
SurfaceControl thumbnail;
|
||||
int thumbnailTransactionSeq;
|
||||
private int mThumbnailLayer;
|
||||
|
||||
Animation thumbnailAnimation;
|
||||
final Transformation thumbnailTransformation = new Transformation();
|
||||
|
||||
// This flag indicates that the destruction of the thumbnail surface is synchronized with
|
||||
// another animation, so defer the destruction of this thumbnail surface for a single frame
|
||||
// after the secondary animation completes.
|
||||
boolean deferThumbnailDestruction;
|
||||
// This flag is set if the animator has deferThumbnailDestruction set and has reached the final
|
||||
// frame of animation. It will extend the animation by one frame and then clean up afterwards.
|
||||
boolean deferFinalFrameCleanup;
|
||||
// If true when the animation hits the last frame, it will keep running on that last frame.
|
||||
// This is used to synchronize animation with Recents and we wait for Recents to tell us to
|
||||
// finish or for a new animation be set as fail-safe mechanism.
|
||||
private int mProlongAnimation;
|
||||
// Whether the prolong animation can be removed when animation is set. The purpose of this is
|
||||
// that if recents doesn't tell us to remove the prolonged animation, we will get rid of it
|
||||
// when new animation is set.
|
||||
private boolean mClearProlongedAnimation;
|
||||
private int mTransit;
|
||||
private int mTransitFlags;
|
||||
|
||||
/** True if the current animation was transferred from another AppWindowAnimator.
|
||||
* See {@link #transferCurrentAnimation}*/
|
||||
boolean usingTransferredAnimation = false;
|
||||
|
||||
private boolean mSkipFirstFrame = false;
|
||||
private int mStackClip = STACK_CLIP_BEFORE_ANIM;
|
||||
|
||||
static final Animation sDummyAnimation = new DummyAnimation();
|
||||
|
||||
public AppWindowAnimator(final AppWindowToken atoken, WindowManagerService service) {
|
||||
mAppToken = atoken;
|
||||
mService = service;
|
||||
mAnimator = mService.mAnimator;
|
||||
}
|
||||
|
||||
public void setAnimation(Animation anim, int width, int height, int parentWidth,
|
||||
int parentHeight, boolean skipFirstFrame, int stackClip, int transit,
|
||||
int transitFlags) {
|
||||
if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting animation in " + mAppToken
|
||||
+ ": " + anim + " wxh=" + width + "x" + height
|
||||
+ " hasContentToDisplay=" + mAppToken.hasContentToDisplay());
|
||||
animation = anim;
|
||||
animating = false;
|
||||
if (!anim.isInitialized()) {
|
||||
anim.initialize(width, height, parentWidth, parentHeight);
|
||||
}
|
||||
anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
|
||||
anim.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked());
|
||||
int zorder = anim.getZAdjustment();
|
||||
int adj = 0;
|
||||
if (zorder == Animation.ZORDER_TOP) {
|
||||
adj = TYPE_LAYER_OFFSET;
|
||||
} else if (zorder == Animation.ZORDER_BOTTOM) {
|
||||
adj = -TYPE_LAYER_OFFSET;
|
||||
}
|
||||
|
||||
if (animLayerAdjustment != adj) {
|
||||
animLayerAdjustment = adj;
|
||||
updateLayers();
|
||||
}
|
||||
// Start out animation gone if window is gone, or visible if window is visible.
|
||||
transformation.clear();
|
||||
transformation.setAlpha(mAppToken.isVisible() ? 1 : 0);
|
||||
hasTransformation = true;
|
||||
mStackClip = stackClip;
|
||||
|
||||
mSkipFirstFrame = skipFirstFrame;
|
||||
mTransit = transit;
|
||||
mTransitFlags = transitFlags;
|
||||
|
||||
if (!mAppToken.fillsParent()) {
|
||||
anim.setBackgroundColor(0);
|
||||
}
|
||||
if (mClearProlongedAnimation) {
|
||||
mProlongAnimation = PROLONG_ANIMATION_DISABLED;
|
||||
} else {
|
||||
mClearProlongedAnimation = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void setDummyAnimation() {
|
||||
if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting dummy animation in " + mAppToken
|
||||
+ " hasContentToDisplay=" + mAppToken.hasContentToDisplay());
|
||||
animation = sDummyAnimation;
|
||||
hasTransformation = true;
|
||||
transformation.clear();
|
||||
transformation.setAlpha(mAppToken.isVisible() ? 1 : 0);
|
||||
}
|
||||
|
||||
void setNullAnimation() {
|
||||
animation = null;
|
||||
usingTransferredAnimation = false;
|
||||
}
|
||||
|
||||
public void clearAnimation() {
|
||||
if (animation != null) {
|
||||
animating = true;
|
||||
}
|
||||
clearThumbnail();
|
||||
setNullAnimation();
|
||||
if (mAppToken.deferClearAllDrawn) {
|
||||
mAppToken.clearAllDrawn();
|
||||
}
|
||||
mStackClip = STACK_CLIP_BEFORE_ANIM;
|
||||
mTransit = TRANSIT_UNSET;
|
||||
mTransitFlags = 0;
|
||||
}
|
||||
|
||||
public boolean isAnimating() {
|
||||
return animation != null || mAppToken.inPendingTransaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether an animation is about to start, i.e. the animation is set already but we
|
||||
* haven't processed the first frame yet.
|
||||
*/
|
||||
boolean isAnimationStarting() {
|
||||
return animation != null && !animating;
|
||||
}
|
||||
|
||||
public int getTransit() {
|
||||
return mTransit;
|
||||
}
|
||||
|
||||
int getTransitFlags() {
|
||||
return mTransitFlags;
|
||||
}
|
||||
|
||||
public void clearThumbnail() {
|
||||
if (thumbnail != null) {
|
||||
thumbnail.hide();
|
||||
mService.mWindowPlacerLocked.destroyAfterTransaction(thumbnail);
|
||||
thumbnail = null;
|
||||
}
|
||||
deferThumbnailDestruction = false;
|
||||
}
|
||||
|
||||
int getStackClip() {
|
||||
return mStackClip;
|
||||
}
|
||||
|
||||
void transferCurrentAnimation(
|
||||
AppWindowAnimator toAppAnimator, WindowStateAnimator transferWinAnimator) {
|
||||
|
||||
if (animation != null) {
|
||||
toAppAnimator.animation = animation;
|
||||
toAppAnimator.animating = animating;
|
||||
toAppAnimator.animLayerAdjustment = animLayerAdjustment;
|
||||
setNullAnimation();
|
||||
animLayerAdjustment = 0;
|
||||
toAppAnimator.updateLayers();
|
||||
updateLayers();
|
||||
toAppAnimator.usingTransferredAnimation = true;
|
||||
toAppAnimator.mTransit = mTransit;
|
||||
}
|
||||
if (transferWinAnimator != null) {
|
||||
toAppAnimator.hasTransformation = transferWinAnimator.mAppAnimator.hasTransformation;
|
||||
if (toAppAnimator.hasTransformation) {
|
||||
toAppAnimator.transformation.set(transferWinAnimator.mAppAnimator.transformation);
|
||||
} else {
|
||||
toAppAnimator.transformation.clear();
|
||||
}
|
||||
transferWinAnimator.mAppAnimator = toAppAnimator;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLayers() {
|
||||
mAppToken.getDisplayContent().assignWindowLayers(false /* relayoutNeeded */);
|
||||
}
|
||||
|
||||
private void stepThumbnailAnimation(long currentTime) {
|
||||
thumbnailTransformation.clear();
|
||||
final long animationFrameTime = getAnimationFrameTime(thumbnailAnimation, currentTime);
|
||||
thumbnailAnimation.getTransformation(animationFrameTime, thumbnailTransformation);
|
||||
|
||||
ScreenRotationAnimation screenRotationAnimation =
|
||||
mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
|
||||
final boolean screenAnimation = screenRotationAnimation != null
|
||||
&& screenRotationAnimation.isAnimating();
|
||||
if (screenAnimation) {
|
||||
thumbnailTransformation.postCompose(screenRotationAnimation.getEnterTransformation());
|
||||
}
|
||||
// cache often used attributes locally
|
||||
final float tmpFloats[] = mService.mTmpFloats;
|
||||
thumbnailTransformation.getMatrix().getValues(tmpFloats);
|
||||
if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
|
||||
"thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X]
|
||||
+ ", " + tmpFloats[Matrix.MTRANS_Y]);
|
||||
thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]);
|
||||
if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
|
||||
"thumbnail", "alpha=" + thumbnailTransformation.getAlpha()
|
||||
+ " layer=" + mThumbnailLayer
|
||||
+ " matrix=[" + tmpFloats[Matrix.MSCALE_X]
|
||||
+ "," + tmpFloats[Matrix.MSKEW_Y]
|
||||
+ "][" + tmpFloats[Matrix.MSKEW_X]
|
||||
+ "," + tmpFloats[Matrix.MSCALE_Y] + "]");
|
||||
thumbnail.setAlpha(thumbnailTransformation.getAlpha());
|
||||
thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
|
||||
tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
|
||||
thumbnail.setWindowCrop(thumbnailTransformation.getClipRect());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sometimes we need to synchronize the first frame of animation with some external event, e.g.
|
||||
* Recents hiding some of its content. To achieve this, we prolong the start of the animaiton
|
||||
* and keep producing the first frame of the animation.
|
||||
*/
|
||||
private long getAnimationFrameTime(Animation animation, long currentTime) {
|
||||
if (mProlongAnimation == PROLONG_ANIMATION_AT_START) {
|
||||
animation.setStartTime(currentTime);
|
||||
return currentTime + 1;
|
||||
}
|
||||
return currentTime;
|
||||
}
|
||||
|
||||
private boolean stepAnimation(long currentTime) {
|
||||
if (animation == null) {
|
||||
return false;
|
||||
}
|
||||
transformation.clear();
|
||||
final long animationFrameTime = getAnimationFrameTime(animation, currentTime);
|
||||
boolean hasMoreFrames = animation.getTransformation(animationFrameTime, transformation);
|
||||
if (!hasMoreFrames) {
|
||||
if (deferThumbnailDestruction && !deferFinalFrameCleanup) {
|
||||
// We are deferring the thumbnail destruction, so extend the animation for one more
|
||||
// (dummy) frame before we clean up
|
||||
deferFinalFrameCleanup = true;
|
||||
hasMoreFrames = true;
|
||||
} else {
|
||||
if (false && DEBUG_ANIM) Slog.v(TAG,
|
||||
"Stepped animation in " + mAppToken + ": more=" + hasMoreFrames +
|
||||
", xform=" + transformation + ", mProlongAnimation=" + mProlongAnimation);
|
||||
deferFinalFrameCleanup = false;
|
||||
if (mProlongAnimation == PROLONG_ANIMATION_AT_END) {
|
||||
hasMoreFrames = true;
|
||||
} else {
|
||||
setNullAnimation();
|
||||
clearThumbnail();
|
||||
if (DEBUG_ANIM) Slog.v(TAG, "Finished animation in " + mAppToken + " @ "
|
||||
+ currentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
hasTransformation = hasMoreFrames;
|
||||
return hasMoreFrames;
|
||||
}
|
||||
|
||||
private long getStartTimeCorrection() {
|
||||
if (mSkipFirstFrame) {
|
||||
|
||||
// If the transition is an animation in which the first frame doesn't change the screen
|
||||
// contents at all, we can just skip it and start at the second frame. So we shift the
|
||||
// start time of the animation forward by minus the frame duration.
|
||||
return -Choreographer.getInstance().getFrameIntervalNanos() / TimeUtils.NANOS_PER_MS;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// This must be called while inside a transaction.
|
||||
boolean stepAnimationLocked(long currentTime) {
|
||||
if (mAppToken.okToAnimate()) {
|
||||
// We will run animations as long as the display isn't frozen.
|
||||
|
||||
if (animation == sDummyAnimation) {
|
||||
// This guy is going to animate, but not yet. For now count
|
||||
// it as not animating for purposes of scheduling transactions;
|
||||
// when it is really time to animate, this will be set to
|
||||
// a real animation and the next call will execute normally.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed)
|
||||
&& animation != null) {
|
||||
if (!animating) {
|
||||
if (DEBUG_ANIM) Slog.v(TAG,
|
||||
"Starting animation in " + mAppToken +
|
||||
" @ " + currentTime + " scale="
|
||||
+ mService.getTransitionAnimationScaleLocked()
|
||||
+ " allDrawn=" + mAppToken.allDrawn + " animating=" + animating);
|
||||
long correction = getStartTimeCorrection();
|
||||
animation.setStartTime(currentTime + correction);
|
||||
animating = true;
|
||||
if (thumbnail != null) {
|
||||
thumbnail.show();
|
||||
thumbnailAnimation.setStartTime(currentTime + correction);
|
||||
}
|
||||
mSkipFirstFrame = false;
|
||||
}
|
||||
if (stepAnimation(currentTime)) {
|
||||
// animation isn't over, step any thumbnail and that's
|
||||
// it for now.
|
||||
if (thumbnail != null) {
|
||||
stepThumbnailAnimation(currentTime);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (animation != null) {
|
||||
// If the display is frozen, and there is a pending animation,
|
||||
// clear it and make sure we run the cleanup code.
|
||||
animating = true;
|
||||
animation = null;
|
||||
}
|
||||
|
||||
hasTransformation = false;
|
||||
|
||||
if (!animating && animation == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mAppToken.setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "AppWindowToken");
|
||||
|
||||
clearAnimation();
|
||||
animating = false;
|
||||
if (animLayerAdjustment != 0) {
|
||||
animLayerAdjustment = 0;
|
||||
updateLayers();
|
||||
}
|
||||
if (mService.mInputMethodTarget != null
|
||||
&& mService.mInputMethodTarget.mAppToken == mAppToken) {
|
||||
mAppToken.getDisplayContent().computeImeTarget(true /* updateImeTarget */);
|
||||
}
|
||||
|
||||
if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + mAppToken
|
||||
+ ": reportedVisible=" + mAppToken.reportedVisible
|
||||
+ " okToDisplay=" + mAppToken.okToDisplay()
|
||||
+ " okToAnimate=" + mAppToken.okToAnimate()
|
||||
+ " startingDisplayed=" + mAppToken.startingDisplayed);
|
||||
|
||||
transformation.clear();
|
||||
|
||||
mAppToken.forAllWindows(WindowState::onExitAnimationDone, false /* traverseTopToBottom */);
|
||||
mService.mAppTransition.notifyAppTransitionFinishedLocked(mAppToken.token);
|
||||
return false;
|
||||
}
|
||||
|
||||
// This must be called while inside a transaction.
|
||||
void showAllWindowsLocked() {
|
||||
mAppToken.forAllWindows(windowState -> {
|
||||
if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
|
||||
windowState.performShowLocked();
|
||||
}, false /* traverseTopToBottom */);
|
||||
}
|
||||
|
||||
void dump(PrintWriter pw, String prefix) {
|
||||
pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
|
||||
pw.print(prefix); pw.print("mAnimator="); pw.println(mAnimator);
|
||||
pw.print(prefix); pw.print("freezingScreen="); pw.print(freezingScreen);
|
||||
pw.print(" allDrawn="); pw.print(allDrawn);
|
||||
pw.print(" animLayerAdjustment="); pw.println(animLayerAdjustment);
|
||||
if (lastFreezeDuration != 0) {
|
||||
pw.print(prefix); pw.print("lastFreezeDuration=");
|
||||
TimeUtils.formatDuration(lastFreezeDuration, pw); pw.println();
|
||||
}
|
||||
if (animating || animation != null) {
|
||||
pw.print(prefix); pw.print("animating="); pw.println(animating);
|
||||
pw.print(prefix); pw.print("animation="); pw.println(animation);
|
||||
pw.print(prefix); pw.print("mTransit="); pw.println(mTransit);
|
||||
pw.print(prefix); pw.print("mTransitFlags="); pw.println(mTransitFlags);
|
||||
}
|
||||
if (hasTransformation) {
|
||||
pw.print(prefix); pw.print("XForm: ");
|
||||
transformation.printShortString(pw);
|
||||
pw.println();
|
||||
}
|
||||
if (thumbnail != null) {
|
||||
pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail);
|
||||
pw.print(" layer="); pw.println(mThumbnailLayer);
|
||||
pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation);
|
||||
pw.print(prefix); pw.print("thumbnailTransformation=");
|
||||
pw.println(thumbnailTransformation.toShortString());
|
||||
}
|
||||
}
|
||||
|
||||
void startProlongAnimation(int prolongType) {
|
||||
mProlongAnimation = prolongType;
|
||||
mClearProlongedAnimation = false;
|
||||
}
|
||||
|
||||
void endProlongedAnimation() {
|
||||
mProlongAnimation = PROLONG_ANIMATION_DISABLED;
|
||||
}
|
||||
|
||||
// This is an animation that does nothing: it just immediately finishes
|
||||
// itself every time it is called. It is used as a stub animation in cases
|
||||
// where we want to synchronize multiple things that may be animating.
|
||||
static final class DummyAnimation extends Animation {
|
||||
@Override
|
||||
public boolean getTransformation(long currentTime, Transformation outTransformation) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
|
||||
|
||||
import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS;
|
||||
@@ -25,7 +24,6 @@ import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
|
||||
@@ -34,16 +32,13 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
import android.app.ActivityManager.TaskSnapshot;
|
||||
import android.content.res.CompatibilityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Debug;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Trace;
|
||||
import android.util.Slog;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.IApplicationToken;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -339,7 +334,7 @@ public class AppWindowContainerController
|
||||
|
||||
if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG_WM, "setAppVisibility("
|
||||
+ mToken + ", visible=" + visible + "): " + mService.mAppTransition
|
||||
+ " hidden=" + wtoken.hidden + " hiddenRequested="
|
||||
+ " hidden=" + wtoken.isHidden() + " hiddenRequested="
|
||||
+ wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6));
|
||||
|
||||
mService.mOpeningApps.remove(wtoken);
|
||||
@@ -364,11 +359,11 @@ public class AppWindowContainerController
|
||||
wtoken.startingMoved = false;
|
||||
// If the token is currently hidden (should be the common case), or has been
|
||||
// stopped, then we need to set up to wait for its windows to be ready.
|
||||
if (wtoken.hidden || wtoken.mAppStopped) {
|
||||
if (wtoken.isHidden() || wtoken.mAppStopped) {
|
||||
wtoken.clearAllDrawn();
|
||||
|
||||
// If the app was already visible, don't reset the waitingToShow state.
|
||||
if (wtoken.hidden) {
|
||||
if (wtoken.isHidden()) {
|
||||
wtoken.waitingToShow = true;
|
||||
}
|
||||
|
||||
@@ -389,21 +384,6 @@ public class AppWindowContainerController
|
||||
// If we are preparing an app transition, then delay changing
|
||||
// the visibility of this token until we execute that transition.
|
||||
if (wtoken.okToAnimate() && mService.mAppTransition.isTransitionSet()) {
|
||||
// A dummy animation is a placeholder animation which informs others that an
|
||||
// animation is going on (in this case an application transition). If the animation
|
||||
// was transferred from another application/animator, no dummy animator should be
|
||||
// created since an animation is already in progress.
|
||||
if (wtoken.mAppAnimator.usingTransferredAnimation
|
||||
&& wtoken.mAppAnimator.animation == null) {
|
||||
Slog.wtf(TAG_WM, "Will NOT set dummy animation on: " + wtoken
|
||||
+ ", using null transferred animation!");
|
||||
}
|
||||
if (!wtoken.mAppAnimator.usingTransferredAnimation &&
|
||||
(!wtoken.startingDisplayed || mService.mSkipAppTransitionAnimation)) {
|
||||
if (DEBUG_APP_TRANSITIONS) Slog.v(
|
||||
TAG_WM, "Setting dummy animation on: " + wtoken);
|
||||
wtoken.mAppAnimator.setDummyAnimation();
|
||||
}
|
||||
wtoken.inPendingTransaction = true;
|
||||
if (visible) {
|
||||
mService.mOpeningApps.add(wtoken);
|
||||
@@ -423,7 +403,7 @@ public class AppWindowContainerController
|
||||
if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
|
||||
+ " adding " + focusedToken + " to mOpeningApps");
|
||||
// Force animation to be loaded.
|
||||
focusedToken.hidden = true;
|
||||
focusedToken.setHidden(true);
|
||||
mService.mOpeningApps.add(focusedToken);
|
||||
}
|
||||
}
|
||||
@@ -710,7 +690,7 @@ public class AppWindowContainerController
|
||||
return;
|
||||
}
|
||||
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + mToken + ": hidden="
|
||||
+ mContainer.hidden + " freezing=" + mContainer.mAppAnimator.freezingScreen);
|
||||
+ mContainer.isHidden() + " freezing=" + mContainer.mAppAnimator.freezingScreen);
|
||||
mContainer.stopFreezingScreen(true, force);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
|
||||
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
|
||||
@@ -54,19 +55,22 @@ import android.annotation.CallSuper;
|
||||
import android.annotation.NonNull;
|
||||
import android.app.Activity;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Binder;
|
||||
import android.os.Debug;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.Trace;
|
||||
import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.IApplicationToken;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.view.animation.Transformation;
|
||||
|
||||
import com.android.internal.util.ToBooleanFunction;
|
||||
import com.android.server.input.InputApplicationHandle;
|
||||
@@ -189,6 +193,21 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
*/
|
||||
private boolean mCanTurnScreenOn = true;
|
||||
|
||||
/**
|
||||
* If we are running an animation, this determines the transition type. Must be one of
|
||||
* AppTransition.TRANSIT_* constants.
|
||||
*/
|
||||
private int mTransit;
|
||||
|
||||
/**
|
||||
* If we are running an animation, this determines the flags during this animation. Must be a
|
||||
* bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
|
||||
*/
|
||||
private int mTransitFlags;
|
||||
|
||||
/** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
|
||||
private boolean mLastSurfaceShowing;
|
||||
|
||||
AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
|
||||
DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
|
||||
boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint,
|
||||
@@ -206,7 +225,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
mRotationAnimationHint = rotationAnimationHint;
|
||||
|
||||
// Application tokens start out hidden.
|
||||
hidden = true;
|
||||
setHidden(true);
|
||||
hiddenRequested = true;
|
||||
}
|
||||
|
||||
@@ -218,7 +237,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
mVoiceInteraction = voiceInteraction;
|
||||
mFillsParent = fillsParent;
|
||||
mInputApplicationHandle = new InputApplicationHandle(this);
|
||||
mAppAnimator = new AppWindowAnimator(this, service);
|
||||
mAppAnimator = new AppWindowAnimator();
|
||||
}
|
||||
|
||||
void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
|
||||
@@ -262,7 +281,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
boolean nowGone = mReportedVisibilityResults.nowGone;
|
||||
|
||||
boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
|
||||
boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !hidden;
|
||||
boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
|
||||
if (!nowGone) {
|
||||
// If the app is not yet gone, then it can only become visible/drawn.
|
||||
if (!nowDrawn) {
|
||||
@@ -325,19 +344,16 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
// transition animation
|
||||
// * or this is an opening app and windows are being replaced.
|
||||
boolean visibilityChanged = false;
|
||||
if (hidden == visible || (hidden && mIsExiting) || (visible && waitingForReplacement())) {
|
||||
if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
|
||||
final AccessibilityController accessibilityController = mService.mAccessibilityController;
|
||||
boolean changed = false;
|
||||
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
|
||||
"Changing app " + this + " hidden=" + hidden + " performLayout=" + performLayout);
|
||||
"Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
|
||||
|
||||
boolean runningAppAnimation = false;
|
||||
|
||||
if (mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
|
||||
mAppAnimator.setNullAnimation();
|
||||
}
|
||||
if (transit != AppTransition.TRANSIT_UNSET) {
|
||||
if (mService.applyAnimationLocked(this, lp, transit, visible, isVoiceInteraction)) {
|
||||
if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
|
||||
delayed = runningAppAnimation = true;
|
||||
}
|
||||
final WindowState window = findMainWindow();
|
||||
@@ -355,7 +371,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
|
||||
}
|
||||
|
||||
hidden = hiddenRequested = !visible;
|
||||
setHidden(!visible);
|
||||
hiddenRequested = !visible;
|
||||
visibilityChanged = true;
|
||||
if (!visible) {
|
||||
stopFreezingScreen(true, true);
|
||||
@@ -373,7 +390,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
}
|
||||
|
||||
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setVisibility: " + this
|
||||
+ ": hidden=" + hidden + " hiddenRequested=" + hiddenRequested);
|
||||
+ ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
|
||||
|
||||
if (changed) {
|
||||
mService.mInputMonitor.setUpdateInputWindowsNeededLw();
|
||||
@@ -386,7 +403,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
}
|
||||
}
|
||||
|
||||
if (mAppAnimator.animation != null) {
|
||||
if (isReallyAnimating()) {
|
||||
delayed = true;
|
||||
}
|
||||
|
||||
@@ -414,7 +431,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
// 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 (hidden && !delayed && !mService.mAppTransition.isTransitionSet()) {
|
||||
if (isHidden() && !delayed && !mService.mAppTransition.isTransitionSet()) {
|
||||
SurfaceControl.openTransaction();
|
||||
for (int i = mChildren.size() - 1; i >= 0; i--) {
|
||||
mChildren.get(i).mWinAnimator.hide("immediately hidden");
|
||||
@@ -487,7 +504,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
boolean isVisible() {
|
||||
// If the app token isn't hidden then it is considered visible and there is no need to check
|
||||
// its children windows to see if they are visible.
|
||||
return !hidden;
|
||||
return !isHidden();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -533,7 +550,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
}
|
||||
|
||||
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
|
||||
+ " animation=" + mAppAnimator.animation + " animating=" + mAppAnimator.animating);
|
||||
+ " animation=" + getAnimation() + " animating=" + isSelfAnimating());
|
||||
|
||||
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
|
||||
+ this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
|
||||
@@ -545,7 +562,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
// If this window was animating, then we need to ensure that the app transition notifies
|
||||
// that animations have completed in WMS.handleAnimatingStoppedAndTransitionLocked(), so
|
||||
// add to that list now
|
||||
if (mAppAnimator.animating) {
|
||||
if (isSelfAnimating()) {
|
||||
mService.mNoAnimationNotifyOnTransitionFinished.add(token);
|
||||
}
|
||||
|
||||
@@ -561,8 +578,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
} else {
|
||||
// Make sure there is no animation running on this token, so any windows associated
|
||||
// with it will be removed as soon as their animations are complete
|
||||
mAppAnimator.clearAnimation();
|
||||
mAppAnimator.animating = false;
|
||||
cancelAnimation();
|
||||
if (stack != null) {
|
||||
stack.mExitingAppTokens.remove(this);
|
||||
}
|
||||
@@ -710,7 +726,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
// We set the hidden state to false for the token from a transferred starting window.
|
||||
// We now reset it back to true since the starting window was the last window in the
|
||||
// token.
|
||||
hidden = true;
|
||||
setHidden(true);
|
||||
}
|
||||
} else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
|
||||
// If this is the last window except for a starting transition window,
|
||||
@@ -756,14 +772,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
final WindowState w = mChildren.get(i);
|
||||
w.setWillReplaceWindow(animate);
|
||||
}
|
||||
if (animate) {
|
||||
// Set-up dummy animation so we can start treating windows associated with this
|
||||
// token like they are in transition before the new app window is ready for us to
|
||||
// run the real transition animation.
|
||||
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
|
||||
"setWillReplaceWindow() Setting dummy animation on: " + this);
|
||||
mAppAnimator.setDummyAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
void setWillReplaceChildWindows() {
|
||||
@@ -1007,7 +1015,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
|
||||
void startFreezingScreen() {
|
||||
if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
|
||||
+ hidden + " freezing=" + mAppAnimator.freezingScreen + " hiddenRequested="
|
||||
+ isHidden() + " freezing=" + mAppAnimator.freezingScreen + " hiddenRequested="
|
||||
+ hiddenRequested);
|
||||
if (!hiddenRequested) {
|
||||
if (!mAppAnimator.freezingScreen) {
|
||||
@@ -1111,14 +1119,14 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
if (fromToken.firstWindowDrawn) {
|
||||
firstWindowDrawn = true;
|
||||
}
|
||||
if (!fromToken.hidden) {
|
||||
hidden = false;
|
||||
if (!fromToken.isHidden()) {
|
||||
setHidden(false);
|
||||
hiddenRequested = false;
|
||||
mHiddenSetFromTransferredStartingWindow = true;
|
||||
}
|
||||
setClientHidden(fromToken.mClientHidden);
|
||||
fromToken.mAppAnimator.transferCurrentAnimation(
|
||||
mAppAnimator, tStartingWindow.mWinAnimator);
|
||||
|
||||
// TODO: Transfer animation
|
||||
|
||||
mService.updateFocusedWindowLocked(
|
||||
UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
|
||||
@@ -1142,17 +1150,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
return true;
|
||||
}
|
||||
|
||||
final AppWindowAnimator tAppAnimator = fromToken.mAppAnimator;
|
||||
final AppWindowAnimator wAppAnimator = mAppAnimator;
|
||||
if (tAppAnimator.thumbnail != null) {
|
||||
// The old token is animating with a thumbnail, transfer that to the new token.
|
||||
if (wAppAnimator.thumbnail != null) {
|
||||
wAppAnimator.thumbnail.destroy();
|
||||
}
|
||||
wAppAnimator.thumbnail = tAppAnimator.thumbnail;
|
||||
wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
|
||||
tAppAnimator.thumbnail = null;
|
||||
}
|
||||
// TODO: Transfer thumbnail
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1207,7 +1206,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
|
||||
// The token has now changed state to having all windows shown... what to do, what to do?
|
||||
if (mAppAnimator.freezingScreen) {
|
||||
mAppAnimator.showAllWindowsLocked();
|
||||
showAllWindowsLocked();
|
||||
stopFreezingScreen(false, true);
|
||||
if (DEBUG_ORIENTATION) Slog.i(TAG,
|
||||
"Setting mOrientationChangeComplete=true because wtoken " + this
|
||||
@@ -1220,7 +1219,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
|
||||
// We can now show all of the drawn windows!
|
||||
if (!mService.mOpeningApps.contains(this)) {
|
||||
mAppAnimator.showAllWindowsLocked();
|
||||
showAllWindowsLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1310,13 +1309,13 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
if (!allDrawn && w.mightAffectAllDrawn()) {
|
||||
if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
|
||||
Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
|
||||
+ ", isAnimationSet=" + winAnimator.isAnimationSet());
|
||||
+ ", isAnimationSet=" + isSelfAnimating());
|
||||
if (!w.isDrawnLw()) {
|
||||
Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
|
||||
+ " pv=" + w.mPolicyVisibility
|
||||
+ " mDrawState=" + winAnimator.drawStateToString()
|
||||
+ " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
|
||||
+ " a=" + winAnimator.isAnimationSet());
|
||||
+ " a=" + isSelfAnimating());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1345,21 +1344,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
return isInterestingAndDrawn;
|
||||
}
|
||||
|
||||
@Override
|
||||
void stepAppWindowsAnimation(long currentTime) {
|
||||
mAppAnimator.wasAnimating = mAppAnimator.animating;
|
||||
if (mAppAnimator.stepAnimationLocked(currentTime)) {
|
||||
mAppAnimator.animating = true;
|
||||
mService.mAnimator.setAnimating(true);
|
||||
mService.mAnimator.mAppWindowAnimating = true;
|
||||
} else if (mAppAnimator.wasAnimating) {
|
||||
// stopped animating, do one more pass through the layout
|
||||
setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
|
||||
DEBUG_LAYOUT_REPEATS ? "appToken " + this + " done" : null);
|
||||
if (DEBUG_ANIM) Slog.v(TAG, "updateWindowsApps...: done animating " + this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
|
||||
// For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
|
||||
@@ -1515,14 +1499,179 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
return mAppAnimator.animLayerAdjustment;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isSelfAnimating() {
|
||||
return mAppAnimator.isAnimating();
|
||||
boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
|
||||
boolean isVoiceInteraction) {
|
||||
|
||||
if (mService.mDisableTransitionAnimation) {
|
||||
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
|
||||
Slog.v(TAG_WM, "applyAnimation: transition animation is disabled. atoken=" + this);
|
||||
}
|
||||
cancelAnimation();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
|
||||
// to animate and it can cause strange artifacts when we unfreeze the display if some
|
||||
// different animation is running.
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
|
||||
if (okToAnimate()) {
|
||||
final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
|
||||
if (a != null) {
|
||||
final AnimationAdapter adapter = new LocalAnimationAdapter(
|
||||
new WindowAnimationSpec(a, new Point()), mService.mSurfaceAnimationRunner);
|
||||
startAnimation(getPendingTransaction(), adapter, !isVisible());
|
||||
if (a.getZAdjustment() == Animation.ZORDER_TOP) {
|
||||
mAppAnimator.animLayerAdjustment = 1;
|
||||
getDisplayContent().assignWindowLayers(false /* setLayoutNeeded */);
|
||||
}
|
||||
mTransit = transit;
|
||||
mTransitFlags = mService.mAppTransition.getTransitFlags();
|
||||
// TODO: Skip first frame and app stack clip mode.
|
||||
}
|
||||
} else {
|
||||
cancelAnimation();
|
||||
}
|
||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||
|
||||
return isReallyAnimating();
|
||||
}
|
||||
|
||||
private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
|
||||
boolean isVoiceInteraction) {
|
||||
final DisplayContent displayContent = getTask().getDisplayContent();
|
||||
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
|
||||
final int width = displayInfo.appWidth;
|
||||
final int height = displayInfo.appHeight;
|
||||
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
|
||||
"applyAnimation: atoken=" + this);
|
||||
|
||||
// Determine the visible rect to calculate the thumbnail clip
|
||||
final WindowState win = findMainWindow();
|
||||
final Rect frame = new Rect(0, 0, width, height);
|
||||
final Rect displayFrame = new Rect(0, 0,
|
||||
displayInfo.logicalWidth, displayInfo.logicalHeight);
|
||||
final Rect insets = new Rect();
|
||||
final Rect stableInsets = new Rect();
|
||||
Rect surfaceInsets = null;
|
||||
final boolean freeform = win != null && win.inFreeformWindowingMode();
|
||||
if (win != null) {
|
||||
// Containing frame will usually cover the whole screen, including dialog windows.
|
||||
// For freeform workspace windows it will not cover the whole screen and it also
|
||||
// won't exactly match the final freeform window frame (e.g. when overlapping with
|
||||
// the status bar). In that case we need to use the final frame.
|
||||
if (freeform) {
|
||||
frame.set(win.mFrame);
|
||||
} else {
|
||||
frame.set(win.mContainingFrame);
|
||||
}
|
||||
surfaceInsets = win.getAttrs().surfaceInsets;
|
||||
insets.set(win.mContentInsets);
|
||||
stableInsets.set(win.mStableInsets);
|
||||
}
|
||||
|
||||
if (mLaunchTaskBehind) {
|
||||
// Differentiate the two animations. This one which is briefly on the screen
|
||||
// gets the !enter animation, and the other activity which remains on the
|
||||
// screen gets the enter animation. Both appear in the mOpeningApps set.
|
||||
enter = false;
|
||||
}
|
||||
if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
|
||||
+ " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
|
||||
+ " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
|
||||
final Configuration displayConfig = displayContent.getConfiguration();
|
||||
final Animation a = mService.mAppTransition.loadAnimation(lp, transit, enter,
|
||||
displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
|
||||
surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
|
||||
if (a != null) {
|
||||
if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
|
||||
final int containingWidth = frame.width();
|
||||
final int containingHeight = frame.height();
|
||||
a.initialize(containingWidth, containingHeight, width, height);
|
||||
a.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked());
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be called while inside a transaction.
|
||||
*/
|
||||
void showAllWindowsLocked() {
|
||||
forAllWindows(windowState -> {
|
||||
if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
|
||||
windowState.performShowLocked();
|
||||
}, false /* traverseTopToBottom */);
|
||||
}
|
||||
|
||||
@Override
|
||||
void dump(PrintWriter pw, String prefix) {
|
||||
super.dump(pw, prefix);
|
||||
protected void onAnimationFinished() {
|
||||
super.onAnimationFinished();
|
||||
|
||||
mTransit = TRANSIT_UNSET;
|
||||
mTransitFlags = 0;
|
||||
mAppAnimator.animLayerAdjustment = 0;
|
||||
|
||||
setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
|
||||
"AppWindowToken");
|
||||
|
||||
if (mService.mInputMethodTarget != null && mService.mInputMethodTarget.mAppToken == this) {
|
||||
getDisplayContent().computeImeTarget(true /* updateImeTarget */);
|
||||
}
|
||||
|
||||
if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
|
||||
+ ": reportedVisible=" + reportedVisible
|
||||
+ " okToDisplay=" + okToDisplay()
|
||||
+ " okToAnimate=" + okToAnimate()
|
||||
+ " startingDisplayed=" + startingDisplayed);
|
||||
|
||||
// WindowState.onExitAnimationDone might modify the children list, so make a copy and then
|
||||
// traverse the copy.
|
||||
final ArrayList<WindowState> children = new ArrayList<>(mChildren);
|
||||
children.forEach(WindowState::onExitAnimationDone);
|
||||
|
||||
mService.mAppTransition.notifyAppTransitionFinishedLocked(token);
|
||||
scheduleAnimation();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isAppAnimating() {
|
||||
return isSelfAnimating();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isSelfAnimating() {
|
||||
// If we are about to start a transition, we also need to be considered animating.
|
||||
return isWaitingForTransitionStart() || isReallyAnimating();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if and only if we are actually running an animation. Note that
|
||||
* {@link #isSelfAnimating} also returns true if we are waiting for an animation to
|
||||
* start.
|
||||
*/
|
||||
private boolean isReallyAnimating() {
|
||||
return super.isSelfAnimating();
|
||||
}
|
||||
|
||||
boolean isWaitingForTransitionStart() {
|
||||
return mService.mAppTransition.isTransitionSet()
|
||||
&& (mService.mOpeningApps.contains(this) || mService.mClosingApps.contains(this));
|
||||
}
|
||||
|
||||
public int getTransit() {
|
||||
return mTransit;
|
||||
}
|
||||
|
||||
int getTransitFlags() {
|
||||
return mTransitFlags;
|
||||
}
|
||||
|
||||
void clearThumbnail() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
|
||||
super.dump(pw, prefix, dumpAll);
|
||||
if (appToken != null) {
|
||||
pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
|
||||
}
|
||||
@@ -1580,9 +1729,27 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
if (mRemovingFromDisplay) {
|
||||
pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
|
||||
}
|
||||
if (mAppAnimator.isAnimating()) {
|
||||
mAppAnimator.dump(pw, prefix + " ");
|
||||
}
|
||||
|
||||
@Override
|
||||
void setHidden(boolean hidden) {
|
||||
super.setHidden(hidden);
|
||||
scheduleAnimation();
|
||||
}
|
||||
|
||||
@Override
|
||||
void prepareSurfaces() {
|
||||
// isSelfAnimating also returns true when we are about to start a transition, so we need
|
||||
// to check super here.
|
||||
final boolean reallyAnimating = super.isSelfAnimating();
|
||||
final boolean show = !isHidden() || reallyAnimating;
|
||||
if (show && !mLastSurfaceShowing) {
|
||||
mPendingTransaction.show(mSurfaceControl);
|
||||
} else if (!show && mLastSurfaceShowing) {
|
||||
mPendingTransaction.hide(mSurfaceControl);
|
||||
}
|
||||
mLastSurfaceShowing = show;
|
||||
super.prepareSurfaces();
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
|
||||
@@ -437,15 +437,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
|
||||
// If this window's app token is running a detached wallpaper animation, make a note so
|
||||
// we can ensure the wallpaper is displayed behind it.
|
||||
final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
|
||||
if (appAnimator != null && appAnimator.animation != null
|
||||
&& appAnimator.animating) {
|
||||
if ((flags & FLAG_SHOW_WALLPAPER) != 0
|
||||
&& appAnimator.animation.getDetachWallpaper()) {
|
||||
final AppWindowToken atoken = winAnimator.mWin.mAppToken;
|
||||
final AnimationAdapter animation = atoken != null ? atoken.getAnimation() : null;
|
||||
if (animation != null) {
|
||||
if ((flags & FLAG_SHOW_WALLPAPER) != 0 && animation.getDetachWallpaper()) {
|
||||
mTmpWindow = w;
|
||||
}
|
||||
|
||||
final int color = appAnimator.animation.getBackgroundColor();
|
||||
final int color = animation.getBackgroundColor();
|
||||
if (color != 0) {
|
||||
final TaskStack stack = w.getStack();
|
||||
if (stack != null) {
|
||||
@@ -528,11 +527,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
+ " screen changed=" + w.isConfigChanged());
|
||||
final AppWindowToken atoken = w.mAppToken;
|
||||
if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + w.mViewVisibility
|
||||
+ " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
|
||||
+ " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
|
||||
+ " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
|
||||
+ " parentHidden=" + w.isParentWindowHidden());
|
||||
else Slog.v(TAG, " VIS: mViewVisibility=" + w.mViewVisibility
|
||||
+ " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
|
||||
+ " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
|
||||
+ " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
|
||||
+ " parentHidden=" + w.isParentWindowHidden());
|
||||
}
|
||||
@@ -707,7 +706,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
}
|
||||
}
|
||||
final TaskStack stack = w.getStack();
|
||||
if ((!winAnimator.isWaitingForOpening())
|
||||
if (!winAnimator.isWaitingForOpening()
|
||||
|| (stack != null && stack.isAnimatingBounds())) {
|
||||
// Updates the shown frame before we set up the surface. This is needed
|
||||
// because the resizing could change the top-left position (in addition to
|
||||
@@ -2169,7 +2168,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
proto.end(token);
|
||||
}
|
||||
|
||||
public void dump(String prefix, PrintWriter pw) {
|
||||
@Override
|
||||
public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
|
||||
super.dump(pw, prefix, dumpAll);
|
||||
pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
|
||||
final String subPrefix = " " + prefix;
|
||||
pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
|
||||
@@ -2203,7 +2204,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
pw.println(prefix + "Application tokens in top down Z order:");
|
||||
for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
|
||||
final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
|
||||
stack.dump(prefix + " ", pw);
|
||||
stack.dump(pw, prefix + " ", dumpAll);
|
||||
}
|
||||
|
||||
pw.println();
|
||||
@@ -2215,7 +2216,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
pw.print(" Exiting #"); pw.print(i);
|
||||
pw.print(' '); pw.print(token);
|
||||
pw.println(':');
|
||||
token.dump(pw, " ");
|
||||
token.dump(pw, " ", dumpAll);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2467,7 +2468,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
// to look at all windows below the current target that are in this app, finding the
|
||||
// highest visible one in layering.
|
||||
WindowState highestTarget = null;
|
||||
if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
|
||||
if (token.isSelfAnimating()) {
|
||||
highestTarget = token.getHighestAnimLayerWindow(curTarget);
|
||||
}
|
||||
|
||||
@@ -2574,7 +2575,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
pw.print(token);
|
||||
if (dumpAll) {
|
||||
pw.println(':');
|
||||
token.dump(pw, " ");
|
||||
token.dump(pw, " ", dumpAll);
|
||||
} else {
|
||||
pw.println();
|
||||
}
|
||||
@@ -3463,8 +3464,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
// Make sure there is no animation running on this token, so any windows
|
||||
// associated with it will be removed as soon as their animations are
|
||||
// complete.
|
||||
token.mAppAnimator.clearAnimation();
|
||||
token.mAppAnimator.animating = false;
|
||||
cancelAnimation();
|
||||
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
|
||||
"performLayout: App token exiting now removed" + token);
|
||||
token.removeIfPossible();
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.os.SystemClock;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
import android.view.animation.Animation;
|
||||
|
||||
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
||||
|
||||
@@ -30,6 +29,7 @@ import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
||||
class LocalAnimationAdapter implements AnimationAdapter {
|
||||
|
||||
private final AnimationSpec mSpec;
|
||||
|
||||
private final SurfaceAnimationRunner mAnimator;
|
||||
|
||||
LocalAnimationAdapter(AnimationSpec spec, SurfaceAnimationRunner animator) {
|
||||
@@ -64,6 +64,11 @@ class LocalAnimationAdapter implements AnimationAdapter {
|
||||
return mSpec.getDuration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStatusBarTransitionsStartTime() {
|
||||
return mSpec.calculateStatusBarTransitionStartTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes how to apply an animation.
|
||||
*/
|
||||
@@ -83,6 +88,13 @@ class LocalAnimationAdapter implements AnimationAdapter {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AnimationAdapter#getStatusBarTransitionsStartTime
|
||||
*/
|
||||
default long calculateStatusBarTransitionStartTime() {
|
||||
return SystemClock.uptimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The duration of the animation.
|
||||
*/
|
||||
@@ -91,8 +103,8 @@ class LocalAnimationAdapter implements AnimationAdapter {
|
||||
/**
|
||||
* Called when the spec needs to apply the current animation state to the leash.
|
||||
*
|
||||
* @param t The transaction to use to apply a transform.
|
||||
* @param leash The leash to apply the state to.
|
||||
* @param t The transaction to use to apply a transform.
|
||||
* @param leash The leash to apply the state to.
|
||||
* @param currentPlayTime The current time of the animation.
|
||||
*/
|
||||
void apply(Transaction t, SurfaceControl leash, long currentPlayTime);
|
||||
|
||||
@@ -612,7 +612,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
|
||||
defaultDisplay.pendingLayoutChanges);
|
||||
}
|
||||
|
||||
if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) {
|
||||
if (!isAppAnimating() && mService.mAppTransition.isRunning()) {
|
||||
// We have finished the animation of an app transition. To do this, we have delayed a
|
||||
// lot of operations like showing and hiding apps, moving apps in Z-order, etc. The app
|
||||
// token list reflects the correct Z-order, but the window list may now be out of sync
|
||||
@@ -1035,7 +1035,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
|
||||
final int count = mChildren.size();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
final DisplayContent displayContent = mChildren.get(i);
|
||||
displayContent.dump(" ", pw);
|
||||
displayContent.dump(pw, " ", true /* dumpAll */);
|
||||
}
|
||||
} else {
|
||||
pw.println(" NO DISPLAY");
|
||||
|
||||
@@ -536,14 +536,14 @@ class Task extends WindowContainer<AppWindowToken> {
|
||||
/** Cancels any running app transitions associated with the task. */
|
||||
void cancelTaskWindowTransition() {
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
mChildren.get(i).mAppAnimator.clearAnimation();
|
||||
mChildren.get(i).cancelAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
/** Cancels any running thumbnail transitions associated with the task. */
|
||||
void cancelTaskThumbnailTransition() {
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
mChildren.get(i).mAppAnimator.clearThumbnail();
|
||||
mChildren.get(i).clearThumbnail();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -677,7 +677,9 @@ class Task extends WindowContainer<AppWindowToken> {
|
||||
proto.end(token);
|
||||
}
|
||||
|
||||
public void dump(String prefix, PrintWriter pw) {
|
||||
@Override
|
||||
public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
|
||||
super.dump(pw, prefix, dumpAll);
|
||||
final String doublePrefix = prefix + " ";
|
||||
|
||||
pw.println(prefix + "taskId=" + mTaskId);
|
||||
@@ -691,7 +693,7 @@ class Task extends WindowContainer<AppWindowToken> {
|
||||
for (int i = mChildren.size() - 1; i >= 0; i--) {
|
||||
final AppWindowToken wtoken = mChildren.get(i);
|
||||
pw.println(triplePrefix + "Activity #" + i + " " + wtoken);
|
||||
wtoken.dump(pw, triplePrefix);
|
||||
wtoken.dump(pw, triplePrefix, dumpAll);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1284,7 +1284,8 @@ public class TaskStack extends WindowContainer<Task> implements
|
||||
proto.end(token);
|
||||
}
|
||||
|
||||
public void dump(String prefix, PrintWriter pw) {
|
||||
@Override
|
||||
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
|
||||
pw.println(prefix + "mStackId=" + mStackId);
|
||||
pw.println(prefix + "mDeferRemoval=" + mDeferRemoval);
|
||||
pw.println(prefix + "mBounds=" + getRawBounds().toShortString());
|
||||
@@ -1300,7 +1301,7 @@ public class TaskStack extends WindowContainer<Task> implements
|
||||
pw.println(prefix + "mAdjustedBounds=" + mAdjustedBounds.toShortString());
|
||||
}
|
||||
for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
|
||||
mChildren.get(taskNdx).dump(prefix + " ", pw);
|
||||
mChildren.get(taskNdx).dump(pw, prefix + " ", dumpAll);
|
||||
}
|
||||
if (mAnimationBackgroundSurfaceIsShown) {
|
||||
pw.println(prefix + "mWindowAnimationBackgroundSurface is shown");
|
||||
@@ -1313,7 +1314,7 @@ public class TaskStack extends WindowContainer<Task> implements
|
||||
pw.print(" Exiting App #"); pw.print(i);
|
||||
pw.print(' '); pw.print(token);
|
||||
pw.println(':');
|
||||
token.dump(pw, " ");
|
||||
token.dump(pw, " ", dumpAll);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1653,35 +1654,6 @@ public class TaskStack extends WindowContainer<Task> implements
|
||||
return super.checkCompleteDeferredRemoval();
|
||||
}
|
||||
|
||||
void stepAppWindowsAnimation(long currentTime) {
|
||||
super.stepAppWindowsAnimation(currentTime);
|
||||
|
||||
// TODO: Why aren't we just using the loop above for this? mAppAnimator.animating isn't set
|
||||
// below but is set in the loop above. See if it really matters...
|
||||
|
||||
// Clear before using.
|
||||
mTmpAppTokens.clear();
|
||||
// We copy the list as things can be removed from the exiting token list while we are
|
||||
// processing.
|
||||
mTmpAppTokens.addAll(mExitingAppTokens);
|
||||
for (int i = 0; i < mTmpAppTokens.size(); i++) {
|
||||
final AppWindowAnimator appAnimator = mTmpAppTokens.get(i).mAppAnimator;
|
||||
appAnimator.wasAnimating = appAnimator.animating;
|
||||
if (appAnimator.stepAnimationLocked(currentTime)) {
|
||||
mService.mAnimator.setAnimating(true);
|
||||
mService.mAnimator.mAppWindowAnimating = true;
|
||||
} else if (appAnimator.wasAnimating) {
|
||||
// stopped animating, do one more pass through the layout
|
||||
appAnimator.mAppToken.setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
|
||||
"exiting appToken " + appAnimator.mAppToken + " done");
|
||||
if (DEBUG_ANIM) Slog.v(TAG_WM,
|
||||
"updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
|
||||
}
|
||||
}
|
||||
// Clear to avoid holding reference to tokens.
|
||||
mTmpAppTokens.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
int getOrientation() {
|
||||
return (canSpecifyOrientation()) ? super.getOrientation() : SCREEN_ORIENTATION_UNSET;
|
||||
|
||||
@@ -112,7 +112,7 @@ class WallpaperController {
|
||||
mFindResults.resetTopWallpaper = true;
|
||||
if (w != winAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
|
||||
// If this window's app token is hidden and not animating, it is of no interest to us.
|
||||
if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
|
||||
if (w.mAppToken.isHidden() && !w.mAppToken.isSelfAnimating()) {
|
||||
if (DEBUG_WALLPAPER) Slog.v(TAG,
|
||||
"Skipping hidden and not animating token: " + w);
|
||||
return false;
|
||||
@@ -130,10 +130,10 @@ class WallpaperController {
|
||||
}
|
||||
|
||||
final boolean keyguardGoingAwayWithWallpaper = (w.mAppToken != null
|
||||
&& AppTransition.isKeyguardGoingAwayTransit(
|
||||
w.mAppToken.mAppAnimator.getTransit())
|
||||
&& (w.mAppToken.mAppAnimator.getTransitFlags()
|
||||
& TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
|
||||
&& w.mAppToken.isSelfAnimating()
|
||||
&& AppTransition.isKeyguardGoingAwayTransit(w.mAppToken.getTransit())
|
||||
&& (w.mAppToken.getTransitFlags()
|
||||
& TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
|
||||
|
||||
boolean needsShowWhenLockedWallpaper = false;
|
||||
if ((w.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
|
||||
@@ -204,18 +204,19 @@ class WallpaperController {
|
||||
private boolean isWallpaperVisible(WindowState wallpaperTarget) {
|
||||
if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
|
||||
+ (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
|
||||
+ " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
|
||||
? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
|
||||
+ " animating=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
|
||||
? wallpaperTarget.mAppToken.isSelfAnimating() : null)
|
||||
+ " prev=" + mPrevWallpaperTarget);
|
||||
return (wallpaperTarget != null
|
||||
&& (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
|
||||
&& wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
|
||||
&& wallpaperTarget.mAppToken.isSelfAnimating())))
|
||||
|| mPrevWallpaperTarget != null;
|
||||
}
|
||||
|
||||
boolean isWallpaperTargetAnimating() {
|
||||
return mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimationSet()
|
||||
&& !mWallpaperTarget.mWinAnimator.isDummyAnimation();
|
||||
&& (mWallpaperTarget.mAppToken == null
|
||||
|| !mWallpaperTarget.mAppToken.isWaitingForTransitionStart());
|
||||
}
|
||||
|
||||
void updateWallpaperVisibility() {
|
||||
@@ -250,7 +251,7 @@ class WallpaperController {
|
||||
for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
|
||||
final WallpaperWindowToken token = mWallpaperTokens.get(i);
|
||||
token.hideWallpaperToken(wasDeferred, "hideWallpapers");
|
||||
if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
|
||||
if (DEBUG_WALLPAPER_LIGHT && !token.isHidden()) Slog.d(TAG, "Hiding wallpaper " + token
|
||||
+ " from " + winGoingAway + " target=" + mWallpaperTarget + " prev="
|
||||
+ mPrevWallpaperTarget + "\n" + Debug.getCallers(5, " "));
|
||||
}
|
||||
|
||||
@@ -16,12 +16,9 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
|
||||
@@ -56,7 +53,7 @@ class WallpaperWindowToken extends WindowToken {
|
||||
final WindowState wallpaper = mChildren.get(j);
|
||||
wallpaper.hideWallpaperWindow(wasDeferred, reason);
|
||||
}
|
||||
hidden = true;
|
||||
setHidden(true);
|
||||
}
|
||||
|
||||
void sendWindowWallpaperCommand(
|
||||
@@ -92,8 +89,9 @@ class WallpaperWindowToken extends WindowToken {
|
||||
final int dw = displayInfo.logicalWidth;
|
||||
final int dh = displayInfo.logicalHeight;
|
||||
|
||||
if (hidden == visible) {
|
||||
hidden = !visible;
|
||||
if (isHidden() == visible) {
|
||||
setHidden(!visible);
|
||||
|
||||
// Need to do a layout to ensure the wallpaper now has the correct size.
|
||||
mDisplayContent.setLayoutNeeded();
|
||||
}
|
||||
@@ -121,10 +119,10 @@ class WallpaperWindowToken extends WindowToken {
|
||||
|
||||
void updateWallpaperWindows(boolean visible, int animLayerAdj) {
|
||||
|
||||
if (hidden == visible) {
|
||||
if (isHidden() == visible) {
|
||||
if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
|
||||
"Wallpaper token " + token + " hidden=" + !visible);
|
||||
hidden = !visible;
|
||||
setHidden(!visible);
|
||||
// Need to do a layout to ensure the wallpaper now has the correct size.
|
||||
mDisplayContent.setLayoutNeeded();
|
||||
}
|
||||
|
||||
@@ -16,11 +16,17 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static com.android.server.wm.AnimationAdapter.STATUS_BAR_TRANSITION_DURATION;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.os.SystemClock;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationSet;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.Transformation;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
|
||||
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
|
||||
|
||||
@@ -61,6 +67,63 @@ public class WindowAnimationSpec implements AnimationSpec {
|
||||
tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);
|
||||
t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats);
|
||||
t.setAlpha(leash, tmp.transformation.getAlpha());
|
||||
t.setWindowCrop(leash, tmp.transformation.getClipRect());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long calculateStatusBarTransitionStartTime() {
|
||||
TranslateAnimation openTranslateAnimation = findTranslateAnimation(mAnimation);
|
||||
if (openTranslateAnimation != null) {
|
||||
|
||||
// Some interpolators are extremely quickly mostly finished, but not completely. For
|
||||
// our purposes, we need to find the fraction for which ther interpolator is mostly
|
||||
// there, and use that value for the calculation.
|
||||
float t = findAlmostThereFraction(openTranslateAnimation.getInterpolator());
|
||||
return SystemClock.uptimeMillis()
|
||||
+ openTranslateAnimation.getStartOffset()
|
||||
+ (long)(openTranslateAnimation.getDuration() * t)
|
||||
- STATUS_BAR_TRANSITION_DURATION;
|
||||
} else {
|
||||
return SystemClock.uptimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to find a {@link TranslateAnimation} inside the {@code animation}.
|
||||
*
|
||||
* @return the found animation, {@code null} otherwise
|
||||
*/
|
||||
private static TranslateAnimation findTranslateAnimation(Animation animation) {
|
||||
if (animation instanceof TranslateAnimation) {
|
||||
return (TranslateAnimation) animation;
|
||||
} else if (animation instanceof AnimationSet) {
|
||||
AnimationSet set = (AnimationSet) animation;
|
||||
for (int i = 0; i < set.getAnimations().size(); i++) {
|
||||
Animation a = set.getAnimations().get(i);
|
||||
if (a instanceof TranslateAnimation) {
|
||||
return (TranslateAnimation) a;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binary searches for a {@code t} such that there exists a {@code -0.01 < eps < 0.01} for which
|
||||
* {@code interpolator(t + eps) > 0.99}.
|
||||
*/
|
||||
private static float findAlmostThereFraction(Interpolator interpolator) {
|
||||
float val = 0.5f;
|
||||
float adj = 0.25f;
|
||||
while (adj >= 0.01f) {
|
||||
if (interpolator.getInterpolation(val) < 0.99f) {
|
||||
val += adj;
|
||||
} else {
|
||||
val -= adj;
|
||||
}
|
||||
adj /= 2;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
private static class TmpValues {
|
||||
|
||||
@@ -52,14 +52,12 @@ public class WindowAnimator {
|
||||
private boolean mAnimating;
|
||||
private boolean mLastAnimating;
|
||||
|
||||
/** Is any app window animating? */
|
||||
boolean mAppWindowAnimating;
|
||||
|
||||
final Choreographer.FrameCallback mAnimationFrameCallback;
|
||||
|
||||
/** Time of current animation step. Reset on each iteration */
|
||||
long mCurrentTime;
|
||||
|
||||
boolean mAppWindowAnimating;
|
||||
/** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
|
||||
* is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
|
||||
int mAnimTransactionSequence;
|
||||
@@ -156,7 +154,6 @@ public class WindowAnimator {
|
||||
mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
|
||||
mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
|
||||
mAnimating = false;
|
||||
mAppWindowAnimating = false;
|
||||
if (DEBUG_WINDOW_TRACE) {
|
||||
Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
|
||||
}
|
||||
@@ -170,7 +167,6 @@ public class WindowAnimator {
|
||||
for (int i = 0; i < numDisplays; i++) {
|
||||
final int displayId = mDisplayContentsAnimators.keyAt(i);
|
||||
final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
|
||||
dc.stepAppWindowsAnimation(mCurrentTime);
|
||||
DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
|
||||
|
||||
final ScreenRotationAnimation screenRotationAnimation =
|
||||
|
||||
@@ -445,6 +445,20 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
return isSelfAnimating() || mParent != null && mParent.isAnimating();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if in this subtree of the hierarchy we have an {@link AppWindowToken}
|
||||
* that is {@link #isSelfAnimating}; {@code false} otherwise.
|
||||
*/
|
||||
boolean isAppAnimating() {
|
||||
for (int j = mChildren.size() - 1; j >= 0; j--) {
|
||||
final WindowContainer wc = mChildren.get(j);
|
||||
if (wc.isAppAnimating()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether our own container running an animation at the moment.
|
||||
*/
|
||||
@@ -532,14 +546,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
}
|
||||
}
|
||||
|
||||
/** Step currently ongoing animation for App window containers. */
|
||||
void stepAppWindowsAnimation(long currentTime) {
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer wc = mChildren.get(i);
|
||||
wc.stepAppWindowsAnimation(currentTime);
|
||||
}
|
||||
}
|
||||
|
||||
void onAppTransitionDone() {
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer wc = mChildren.get(i);
|
||||
@@ -1059,6 +1065,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
return mSurfaceControl.getHeight();
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
|
||||
if (mSurfaceAnimator.isAnimating()) {
|
||||
pw.print(prefix); pw.println("ContainerAnimator:");
|
||||
|
||||
@@ -118,8 +118,11 @@ public abstract class WindowManagerInternal {
|
||||
* of AppTransition.TRANSIT_* values
|
||||
* @param openToken the token for the opening app
|
||||
* @param closeToken the token for the closing app
|
||||
* @param openAnimation the animation for the opening app
|
||||
* @param closeAnimation the animation for the closing app
|
||||
* @param duration the total duration of the transition
|
||||
* @param statusBarAnimationStartTime the desired start time for all visual animations in
|
||||
* the status bar caused by this app transition in uptime millis
|
||||
* @param statusBarAnimationDuration the duration for all visual animations in the status
|
||||
* bar caused by this app transition in millis
|
||||
*
|
||||
* @return Return any bit set of {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_LAYOUT},
|
||||
* {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_CONFIG},
|
||||
@@ -127,7 +130,7 @@ public abstract class WindowManagerInternal {
|
||||
* or {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_ANIM}.
|
||||
*/
|
||||
public int onAppTransitionStartingLocked(int transit, IBinder openToken, IBinder closeToken,
|
||||
Animation openAnimation, Animation closeAnimation) {
|
||||
long duration, long statusBarAnimationStartTime, long statusBarAnimationDuration) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -566,12 +566,10 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
int mDockedStackCreateMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
|
||||
Rect mDockedStackCreateBounds;
|
||||
|
||||
private final SparseIntArray mTmpTaskIds = new SparseIntArray();
|
||||
|
||||
boolean mForceResizableTasks = false;
|
||||
boolean mSupportsPictureInPicture = false;
|
||||
|
||||
private boolean mDisableTransitionAnimation = false;
|
||||
boolean mDisableTransitionAnimation = false;
|
||||
|
||||
int getDragLayerLocked() {
|
||||
return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
|
||||
@@ -2279,83 +2277,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
boolean applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp,
|
||||
int transit, boolean enter, boolean isVoiceInteraction) {
|
||||
if (mDisableTransitionAnimation) {
|
||||
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
|
||||
Slog.v(TAG_WM,
|
||||
"applyAnimation: transition animation is disabled. atoken=" + atoken);
|
||||
}
|
||||
atoken.mAppAnimator.clearAnimation();
|
||||
return false;
|
||||
}
|
||||
// Only apply an animation if the display isn't frozen. If it is
|
||||
// frozen, there is no reason to animate and it can cause strange
|
||||
// artifacts when we unfreeze the display if some different animation
|
||||
// is running.
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
|
||||
if (atoken.okToAnimate()) {
|
||||
final DisplayContent displayContent = atoken.getTask().getDisplayContent();
|
||||
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
|
||||
final int width = displayInfo.appWidth;
|
||||
final int height = displayInfo.appHeight;
|
||||
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
|
||||
"applyAnimation: atoken=" + atoken);
|
||||
|
||||
// Determine the visible rect to calculate the thumbnail clip
|
||||
final WindowState win = atoken.findMainWindow();
|
||||
final Rect frame = new Rect(0, 0, width, height);
|
||||
final Rect displayFrame = new Rect(0, 0,
|
||||
displayInfo.logicalWidth, displayInfo.logicalHeight);
|
||||
final Rect insets = new Rect();
|
||||
final Rect stableInsets = new Rect();
|
||||
Rect surfaceInsets = null;
|
||||
final boolean freeform = win != null && win.inFreeformWindowingMode();
|
||||
if (win != null) {
|
||||
// Containing frame will usually cover the whole screen, including dialog windows.
|
||||
// For freeform workspace windows it will not cover the whole screen and it also
|
||||
// won't exactly match the final freeform window frame (e.g. when overlapping with
|
||||
// the status bar). In that case we need to use the final frame.
|
||||
if (freeform) {
|
||||
frame.set(win.mFrame);
|
||||
} else {
|
||||
frame.set(win.mContainingFrame);
|
||||
}
|
||||
surfaceInsets = win.getAttrs().surfaceInsets;
|
||||
insets.set(win.mContentInsets);
|
||||
stableInsets.set(win.mStableInsets);
|
||||
}
|
||||
|
||||
if (atoken.mLaunchTaskBehind) {
|
||||
// Differentiate the two animations. This one which is briefly on the screen
|
||||
// gets the !enter animation, and the other activity which remains on the
|
||||
// screen gets the enter animation. Both appear in the mOpeningApps set.
|
||||
enter = false;
|
||||
}
|
||||
if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
|
||||
+ " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
|
||||
+ " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
|
||||
final Configuration displayConfig = displayContent.getConfiguration();
|
||||
Animation a = mAppTransition.loadAnimation(lp, transit, enter, displayConfig.uiMode,
|
||||
displayConfig.orientation, frame, displayFrame, insets, surfaceInsets,
|
||||
stableInsets, isVoiceInteraction, freeform, atoken.getTask().mTaskId);
|
||||
if (a != null) {
|
||||
if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
|
||||
final int containingWidth = frame.width();
|
||||
final int containingHeight = frame.height();
|
||||
atoken.mAppAnimator.setAnimation(a, containingWidth, containingHeight, width,
|
||||
height, mAppTransition.canSkipFirstFrame(),
|
||||
mAppTransition.getAppStackClipMode(),
|
||||
transit, mAppTransition.getTransitFlags());
|
||||
}
|
||||
} else {
|
||||
atoken.mAppAnimator.clearAnimation();
|
||||
}
|
||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||
|
||||
return atoken.mAppAnimator.animation != null;
|
||||
}
|
||||
|
||||
boolean checkCallingPermission(String permission, String func) {
|
||||
// Quick check: if the calling permission is me, it's all okay.
|
||||
if (Binder.getCallingPid() == myPid()) {
|
||||
@@ -2701,7 +2622,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
synchronized (mWindowMap) {
|
||||
mAppTransition.overridePendingAppTransitionMultiThumb(specs, onAnimationStartedCallback,
|
||||
onAnimationFinishedCallback, scaleUp);
|
||||
prolongAnimationsFromSpecs(specs, scaleUp);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2712,27 +2632,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
void prolongAnimationsFromSpecs(@NonNull AppTransitionAnimationSpec[] specs, boolean scaleUp) {
|
||||
// This is used by freeform <-> recents windows transition. We need to synchronize
|
||||
// the animation with the appearance of the content of recents, so we will make
|
||||
// animation stay on the first or last frame a little longer.
|
||||
mTmpTaskIds.clear();
|
||||
for (int i = specs.length - 1; i >= 0; i--) {
|
||||
mTmpTaskIds.put(specs[i].taskId, 0);
|
||||
}
|
||||
for (final WindowState win : mWindowMap.values()) {
|
||||
final Task task = win.getTask();
|
||||
if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1
|
||||
&& task.inFreeformWindowingMode()) {
|
||||
final AppWindowToken appToken = win.mAppToken;
|
||||
if (appToken != null && appToken.mAppAnimator != null) {
|
||||
appToken.mAppAnimator.startProlongAnimation(scaleUp ?
|
||||
PROLONG_ANIMATION_AT_START : PROLONG_ANIMATION_AT_END);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void overridePendingAppTransitionInPlace(String packageName, int anim) {
|
||||
synchronized(mWindowMap) {
|
||||
@@ -2756,7 +2655,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
for (final WindowState win : mWindowMap.values()) {
|
||||
final AppWindowToken appToken = win.mAppToken;
|
||||
if (appToken != null && appToken.mAppAnimator != null) {
|
||||
appToken.mAppAnimator.endProlongedAnimation();
|
||||
appToken.endDelayingAnimationStart();
|
||||
}
|
||||
}
|
||||
mAppTransition.notifyProlongedAnimationsEnded();
|
||||
@@ -2811,15 +2710,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) {
|
||||
if (transit != TRANSIT_UNSET) {
|
||||
if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
|
||||
wtoken.mAppAnimator.setNullAnimation();
|
||||
}
|
||||
applyAnimationLocked(wtoken, null, transit, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDockedStackCreateState(int mode, Rect bounds) {
|
||||
synchronized (mWindowMap) {
|
||||
setDockedStackCreateStateLocked(mode, bounds);
|
||||
|
||||
@@ -1432,7 +1432,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
*/
|
||||
// TODO: Can we consolidate this with #isVisible() or have a more appropriate name for this?
|
||||
boolean isWinVisibleLw() {
|
||||
return (mAppToken == null || !mAppToken.hiddenRequested || mAppToken.mAppAnimator.animating)
|
||||
return (mAppToken == null || !mAppToken.hiddenRequested || mAppToken.isSelfAnimating())
|
||||
&& isVisible();
|
||||
}
|
||||
|
||||
@@ -1441,7 +1441,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
* not the pending requested hidden state.
|
||||
*/
|
||||
boolean isVisibleNow() {
|
||||
return (!mToken.hidden || mAttrs.type == TYPE_APPLICATION_STARTING)
|
||||
return (!mToken.isHidden() || mAttrs.type == TYPE_APPLICATION_STARTING)
|
||||
&& isVisible();
|
||||
}
|
||||
|
||||
@@ -1479,7 +1479,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
final AppWindowToken atoken = mAppToken;
|
||||
if (atoken != null) {
|
||||
return ((!isParentWindowHidden() && !atoken.hiddenRequested)
|
||||
|| mWinAnimator.isAnimationSet() || atoken.mAppAnimator.animation != null);
|
||||
|| mWinAnimator.isAnimationSet());
|
||||
}
|
||||
return !isParentWindowHidden() || mWinAnimator.isAnimationSet();
|
||||
}
|
||||
@@ -1513,33 +1513,21 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
return false;
|
||||
}
|
||||
return mHasSurface && mPolicyVisibility && !mDestroying
|
||||
&& ((!isParentWindowHidden() && mViewVisibility == View.VISIBLE && !mToken.hidden)
|
||||
|| mWinAnimator.isAnimationSet()
|
||||
|| ((mAppToken != null) && (mAppToken.mAppAnimator.animation != null)));
|
||||
&& ((!isParentWindowHidden() && mViewVisibility == View.VISIBLE && !mToken.isHidden())
|
||||
|| mWinAnimator.isAnimationSet());
|
||||
}
|
||||
|
||||
// TODO: Another visibility method that was added late in the release to minimize risk.
|
||||
@Override
|
||||
public boolean canAffectSystemUiFlags() {
|
||||
final boolean shown = mWinAnimator.getShown();
|
||||
|
||||
// We only consider the app to be exiting when the animation has started. After the app
|
||||
// transition is executed the windows are marked exiting before the new windows have been
|
||||
// shown. Thus, wait considering a window to be exiting after the animation has actually
|
||||
// started.
|
||||
final boolean appAnimationStarting = mAppToken != null
|
||||
&& mAppToken.mAppAnimator.isAnimationStarting();
|
||||
final boolean exitingSelf = mAnimatingExit && !appAnimationStarting;
|
||||
final boolean appExiting = mAppToken != null && mAppToken.hidden && !appAnimationStarting;
|
||||
|
||||
final boolean exiting = exitingSelf || mDestroying || appExiting;
|
||||
final boolean translucent = mAttrs.alpha == 0.0f;
|
||||
|
||||
// If we are entering with a dummy animation, avoid affecting SystemUI flags until the
|
||||
// transition is starting.
|
||||
final boolean enteringWithDummyAnimation =
|
||||
mWinAnimator.isDummyAnimation() && mWinAnimator.mShownAlpha == 0f;
|
||||
return shown && !exiting && !translucent && !enteringWithDummyAnimation;
|
||||
if (mAppToken == null) {
|
||||
final boolean shown = mWinAnimator.getShown();
|
||||
final boolean exiting = mAnimatingExit || mDestroying;
|
||||
return shown && !exiting && !translucent;
|
||||
} else {
|
||||
return !mAppToken.isHidden();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1550,10 +1538,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
public boolean isDisplayedLw() {
|
||||
final AppWindowToken atoken = mAppToken;
|
||||
return isDrawnLw() && mPolicyVisibility
|
||||
&& ((!isParentWindowHidden() &&
|
||||
(atoken == null || !atoken.hiddenRequested))
|
||||
|| mWinAnimator.isAnimationSet()
|
||||
|| (atoken != null && atoken.mAppAnimator.animation != null));
|
||||
&& ((!isParentWindowHidden() && (atoken == null || !atoken.hiddenRequested))
|
||||
|| mWinAnimator.isAnimationSet());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1561,8 +1547,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
*/
|
||||
@Override
|
||||
public boolean isAnimatingLw() {
|
||||
return mWinAnimator.isAnimationSet()
|
||||
|| (mAppToken != null && mAppToken.mAppAnimator.animation != null);
|
||||
return isAnimating();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1570,7 +1555,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
final AppWindowToken atoken = mAppToken;
|
||||
return mViewVisibility == View.GONE
|
||||
|| !mRelayoutCalled
|
||||
|| (atoken == null && mToken.hidden)
|
||||
|| (atoken == null && mToken.isHidden())
|
||||
|| (atoken != null && atoken.hiddenRequested)
|
||||
|| isParentWindowHidden()
|
||||
|| (mAnimatingExit && !isAnimatingLw())
|
||||
@@ -1608,8 +1593,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
// to determine if it's occluding apps.
|
||||
return ((!mIsWallpaper && mAttrs.format == PixelFormat.OPAQUE)
|
||||
|| (mIsWallpaper && mWallpaperVisible))
|
||||
&& isDrawnLw() && !mWinAnimator.isAnimationSet()
|
||||
&& (mAppToken == null || mAppToken.mAppAnimator.animation == null);
|
||||
&& isDrawnLw() && !mWinAnimator.isAnimationSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1631,7 +1615,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
// 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() && mAppToken.mAppAnimator.isAnimating()) {
|
||||
if (!visible && isVisibleNow() && mAppToken.isSelfAnimating()) {
|
||||
mAnimatingExit = true;
|
||||
mRemoveOnExit = true;
|
||||
mWindowRemovalAllowed = true;
|
||||
@@ -1908,7 +1892,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
+ " surfaceShowing=" + mWinAnimator.getShown()
|
||||
+ " isAnimationSet=" + mWinAnimator.isAnimationSet()
|
||||
+ " app-animation="
|
||||
+ (mAppToken != null ? mAppToken.mAppAnimator.animation : null)
|
||||
+ (mAppToken != null ? mAppToken.isSelfAnimating() : "false")
|
||||
+ " mWillReplaceWindow=" + mWillReplaceWindow
|
||||
+ " inPendingTransaction="
|
||||
+ (mAppToken != null ? mAppToken.inPendingTransaction : false)
|
||||
@@ -1968,8 +1952,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
mService.mAccessibilityController.onWindowTransitionLocked(this, transit);
|
||||
}
|
||||
}
|
||||
final boolean isAnimating =
|
||||
mWinAnimator.isAnimationSet() && !mWinAnimator.isDummyAnimation();
|
||||
final boolean isAnimating = mWinAnimator.isAnimationSet()
|
||||
&& (mAppToken == null || !mAppToken.isWaitingForTransitionStart());
|
||||
final boolean lastWindowIsStartingWindow = startingWindow && mAppToken != null
|
||||
&& mAppToken.isLastWindow(this);
|
||||
// We delay the removal of a window if it has a showing surface that can be used to run
|
||||
@@ -3697,10 +3681,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
+ " parentHidden=" + isParentWindowHidden()
|
||||
+ " tok.hiddenRequested="
|
||||
+ (mAppToken != null && mAppToken.hiddenRequested)
|
||||
+ " tok.hidden=" + (mAppToken != null && mAppToken.hidden)
|
||||
+ " tok.hidden=" + (mAppToken != null && mAppToken.isHidden())
|
||||
+ " animationSet=" + mWinAnimator.isAnimationSet()
|
||||
+ " tok animating="
|
||||
+ (mWinAnimator.mAppAnimator != null && mWinAnimator.mAppAnimator.animating)
|
||||
+ (mAppToken != null && mAppToken.isSelfAnimating())
|
||||
+ " Callers=" + Debug.getCallers(4));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
|
||||
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
|
||||
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
|
||||
import static com.android.server.wm.AppWindowAnimator.sDummyAnimation;
|
||||
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
|
||||
@@ -242,17 +241,12 @@ class WindowStateAnimator {
|
||||
return mWin.isAnimating();
|
||||
}
|
||||
|
||||
/** Is the window animating the DummyAnimation? */
|
||||
boolean isDummyAnimation() {
|
||||
return mAppAnimator != null
|
||||
&& mAppAnimator.animation == sDummyAnimation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this window currently waiting to run an opening animation?
|
||||
*/
|
||||
boolean isWaitingForOpening() {
|
||||
return mService.mAppTransition.isTransitionSet() && isDummyAnimation()
|
||||
return mService.mAppTransition.isTransitionSet()
|
||||
&& (mWin.mAppToken != null && mWin.mAppToken.isHidden())
|
||||
&& mService.mOpeningApps.contains(mWin.mAppToken);
|
||||
}
|
||||
|
||||
@@ -423,7 +417,7 @@ class WindowStateAnimator {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mWin.mAppToken.mAppAnimator.animation == null) {
|
||||
if (!mWin.mAppToken.isSelfAnimating()) {
|
||||
mWin.mAppToken.clearAllDrawn();
|
||||
} else {
|
||||
// Currently animating, persist current state of allDrawn until animation
|
||||
@@ -914,12 +908,13 @@ class WindowStateAnimator {
|
||||
}
|
||||
|
||||
private int resolveStackClip() {
|
||||
// App animation overrides window animation stack clip mode.
|
||||
// TODO
|
||||
/*// App animation overrides window animation stack clip mode.
|
||||
if (mAppAnimator != null && mAppAnimator.animation != null) {
|
||||
return mAppAnimator.getStackClip();
|
||||
} else {
|
||||
} else {*/
|
||||
return STACK_CLIP_AFTER_ANIM;
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
private boolean shouldCropToStackBounds() {
|
||||
|
||||
@@ -361,14 +361,9 @@ class WindowSurfacePlacer {
|
||||
|
||||
mService.mAppTransition.setLastAppTransition(transit, topOpeningApp, topClosingApp);
|
||||
|
||||
final AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
|
||||
topOpeningApp.mAppAnimator;
|
||||
final AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
|
||||
topClosingApp.mAppAnimator;
|
||||
|
||||
final int flags = mService.mAppTransition.getTransitFlags();
|
||||
int layoutRedo = mService.mAppTransition.goodToGo(transit, openingAppAnimator,
|
||||
closingAppAnimator, mService.mOpeningApps, mService.mClosingApps);
|
||||
int layoutRedo = mService.mAppTransition.goodToGo(transit, topOpeningApp,
|
||||
topClosingApp, mService.mOpeningApps, mService.mClosingApps);
|
||||
handleNonAppWindowsInTransition(transit, flags);
|
||||
mService.mAppTransition.postAnimationCallback();
|
||||
mService.mAppTransition.clear();
|
||||
@@ -408,11 +403,6 @@ class WindowSurfacePlacer {
|
||||
final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
|
||||
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
|
||||
|
||||
if (!appAnimator.usingTransferredAnimation) {
|
||||
appAnimator.clearThumbnail();
|
||||
appAnimator.setNullAnimation();
|
||||
}
|
||||
|
||||
if (!wtoken.setVisibility(animLp, true, transit, false, voiceInteraction)){
|
||||
// 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
|
||||
@@ -426,13 +416,12 @@ class WindowSurfacePlacer {
|
||||
">>> OPEN TRANSACTION handleAppTransitionReadyLocked()");
|
||||
mService.openSurfaceTransaction();
|
||||
try {
|
||||
appAnimator.showAllWindowsLocked();
|
||||
wtoken.showAllWindowsLocked();
|
||||
} finally {
|
||||
mService.closeSurfaceTransaction("handleAppTransitionReadyLocked");
|
||||
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
|
||||
"<<< CLOSE TRANSACTION handleAppTransitionReadyLocked()");
|
||||
}
|
||||
mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
|
||||
|
||||
if (animLp != null) {
|
||||
final int layer = wtoken.getHighestAnimLayer();
|
||||
@@ -455,10 +444,7 @@ class WindowSurfacePlacer {
|
||||
for (int i = 0; i < appsCount; i++) {
|
||||
AppWindowToken wtoken = mService.mClosingApps.valueAt(i);
|
||||
|
||||
final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
|
||||
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
|
||||
appAnimator.clearThumbnail();
|
||||
appAnimator.setNullAnimation();
|
||||
// TODO: Do we need to add to mNoAnimationNotifyOnTransitionFinished like above if not
|
||||
// animating?
|
||||
wtoken.setVisibility(animLp, false, transit, false, voiceInteraction);
|
||||
@@ -474,7 +460,6 @@ class WindowSurfacePlacer {
|
||||
&& wtoken.getController() != null) {
|
||||
wtoken.getController().removeStartingWindow();
|
||||
}
|
||||
mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
|
||||
|
||||
if (animLp != null) {
|
||||
int layer = wtoken.getHighestAnimLayer();
|
||||
@@ -661,22 +646,19 @@ class WindowSurfacePlacer {
|
||||
final WindowState win = mService.getDefaultDisplayContentLocked().findFocusedWindow();
|
||||
if (win != null) {
|
||||
final AppWindowToken wtoken = win.mAppToken;
|
||||
final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
|
||||
if (DEBUG_APP_TRANSITIONS)
|
||||
Slog.v(TAG, "Now animating app in place " + wtoken);
|
||||
appAnimator.clearThumbnail();
|
||||
appAnimator.setNullAnimation();
|
||||
mService.updateTokenInPlaceLocked(wtoken, transit);
|
||||
wtoken.cancelAnimation();
|
||||
wtoken.applyAnimationLocked(null, transit, false, false);
|
||||
wtoken.updateReportedVisibilityLocked();
|
||||
mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
|
||||
appAnimator.showAllWindowsLocked();
|
||||
wtoken.showAllWindowsLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createThumbnailAppAnimator(int transit, AppWindowToken appToken) {
|
||||
AppWindowAnimator openingAppAnimator = (appToken == null) ? null : appToken.mAppAnimator;
|
||||
if (openingAppAnimator == null || openingAppAnimator.animation == null) {
|
||||
if (appToken == null || !appToken.isSelfAnimating()) {
|
||||
return;
|
||||
}
|
||||
final int taskId = appToken.getTask().mTaskId;
|
||||
@@ -752,7 +734,7 @@ class WindowSurfacePlacer {
|
||||
} catch (Surface.OutOfResourcesException e) {
|
||||
Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w="
|
||||
+ dirty.width() + " h=" + dirty.height(), e);
|
||||
openingAppAnimator.clearThumbnail();
|
||||
appToken.clearThumbnail();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ class WindowToken extends WindowContainer<WindowState> {
|
||||
boolean paused = false;
|
||||
|
||||
// Should this token's windows be hidden?
|
||||
boolean hidden;
|
||||
private boolean mHidden;
|
||||
|
||||
// Temporary for finding which tokens no longer have visible windows.
|
||||
boolean hasVisible;
|
||||
@@ -112,6 +112,16 @@ class WindowToken extends WindowContainer<WindowState> {
|
||||
onDisplayChanged(dc);
|
||||
}
|
||||
|
||||
void setHidden(boolean hidden) {
|
||||
if (hidden != mHidden) {
|
||||
mHidden = hidden;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isHidden() {
|
||||
return mHidden;
|
||||
}
|
||||
|
||||
void removeAllWindowsIfPossible() {
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
final WindowState win = mChildren.get(i);
|
||||
@@ -130,7 +140,7 @@ class WindowToken extends WindowContainer<WindowState> {
|
||||
// This token is exiting, so allow it to be removed when it no longer contains any windows.
|
||||
mPersistOnEmpty = false;
|
||||
|
||||
if (hidden) {
|
||||
if (mHidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -146,7 +156,7 @@ class WindowToken extends WindowContainer<WindowState> {
|
||||
changed |= win.onSetAppExiting();
|
||||
}
|
||||
|
||||
hidden = true;
|
||||
setHidden(true);
|
||||
|
||||
if (changed) {
|
||||
mService.mWindowPlacerLocked.performSurfacePlacement();
|
||||
@@ -274,10 +284,11 @@ class WindowToken extends WindowContainer<WindowState> {
|
||||
proto.end(token);
|
||||
}
|
||||
|
||||
void dump(PrintWriter pw, String prefix) {
|
||||
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
|
||||
super.dump(pw, prefix, dumpAll);
|
||||
pw.print(prefix); pw.print("windows="); pw.println(mChildren);
|
||||
pw.print(prefix); pw.print("windowType="); pw.print(windowType);
|
||||
pw.print(" hidden="); pw.print(hidden);
|
||||
pw.print(" hidden="); pw.print(mHidden);
|
||||
pw.print(" hasVisible="); pw.println(hasVisible);
|
||||
if (waitingToShow || sendingToBottom) {
|
||||
pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
|
||||
|
||||
@@ -193,7 +193,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
||||
assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mToken.getOrientation());
|
||||
|
||||
mToken.setFillsParent(true);
|
||||
mToken.hidden = true;
|
||||
token.setHidden(true);
|
||||
mToken.sendingToBottom = true;
|
||||
// Can not specify orientation if app isn't visible even though it fills parent.
|
||||
assertEquals(SCREEN_ORIENTATION_UNSET, mToken.getOrientation());
|
||||
|
||||
Reference in New Issue
Block a user