并不是所有窗口动画都是由或经由 shell-transitions 执行的,有一类窗口动画,称之为local animation(本地动画),是在 WM-Core 侧执行的。例如,窗口的异步旋转,或者窗口的退出动画。
local animation 框架的时序图,如下
sequenceDiagram
调用方 ->> WindowContainer: startAnimation()
WindowContainer ->> SurfaceAnimator: startAnimation()
SurfaceAnimator ->> SurfaceAnimator: createAnimationLeash()
Note right of SurfaceAnimator: 创建 leash,并把 WC surface reparent 到 leash
SurfaceAnimator -->> WindowContainer: onAnimationLeashCreated()
Note over SurfaceAnimator,WindowContainer: WC 保存 leash,还会更新 layer
SurfaceAnimator ->> AnimationAdapter: startAnimation(leash)
AnimationAdapter ->> SurfaceAnimationRunner: startAnimation(AnimationSpec, lesh)
SurfaceAnimationRunner ->> +Choreagrapher: postFrameCallback()
Note right of SurfaceAnimationRunner: 类型为 CALLBACK_ANIMATION
Choreagrapher -->> -SurfaceAnimationRunner: startAnimations()
SurfaceAnimationRunner ->> ValueAnimator: addUpdateListener()
SurfaceAnimationRunner ->> ValueAnimator: addListener()
ValueAnimator -->> SurfaceAnimationRunner: onAnimationUpdate()
activate SurfaceAnimationRunner
rect rgb(191, 223, 255)
SurfaceAnimationRunner ->> +SurfaceAnimationRunner: applyTransformation(mFrameTransaction)
SurfaceAnimationRunner ->> -AnimationSpec: apply()
Note over SurfaceAnimationRunner,AnimationSpec: AnimationSpec 从 Animation 获取 transformation,使用 mFrameTransaction ,利用 transformation 操作 leash
end
rect rgb(200, 150, 255)
SurfaceAnimationRunner ->> +SurfaceAnimationRunner: scheduleApplyTransaction()
SurfaceAnimationRunner ->> -Choreagrapher: postCallback(CALLBACK_TRAVERSAL)
Note over SurfaceAnimationRunner, Choreagrapher: apply mFrameTransaction,即执行对 leash 操作
end
deactivate SurfaceAnimationRunner
ValueAnimator -->> SurfaceAnimationRunner: onAnimationEnd()
SurfaceAnimationRunner -->> SurfaceAnimator: onAnimationFinished()
SurfaceAnimator -->> SurfaceAnimator: reset()
Note right of SurfaceAnimator: WindowContainer 复位,并 remove leash
SurfaceAnimator -->> WindowContainer: onAnimationFinished()
SurfaceAnimator -->> 调用方: onAnimationFinished()
介绍下涉及的几个类
- SurfaceAnimator:它是 WindowContainer 的一个成员变量,在 local animation 中,它会创建 leash,并把 WindowContainer surface reparent 到 leash 上,然后把 leash 发送给 AnimationAdapter 去执行动画。
- AnimationAdaper: 它是一个动画适配器,它会把数据交给 SurfaceAnimationRunner 去真正的执行动画。它主要持有的数据是 AnimationSpec。
- SurfaceAnimationRunner: 它是动画的真正执行者,它使用 ValueAnimator 对 leash 执行动画。更重要的是,执行动画时,它不需要持有 WindowManager lock。
- AnimationSpec:从命名可以看出,它保存动画参数,在执行动画时,会先从它获取动画的数据,然后应用到 leash 上。
local animation 是通过 WindowContainer#startAnimation() 开始,如下
// WindowContainer.java
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
@AnimationType int type) {
startAnimation(t, anim, hidden, type, null /* animationFinishedCallback */);
}
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
@AnimationType int type,
@Nullable OnAnimationFinishedCallback animationFinishedCallback) {
startAnimation(t, anim, hidden, type, animationFinishedCallback,
null /* adapterAnimationCancelledCallback */, null /* snapshotAnim */);
}
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
@AnimationType int type,
@Nullable OnAnimationFinishedCallback animationFinishedCallback,
@Nullable Runnable animationCancelledCallback,
@Nullable AnimationAdapter snapshotAnim) {
ProtoLog.v(WM_DEBUG_ANIM, "Starting animation on %s: type=%d, anim=%s",
this, type, anim);
// 交给 SurfaceAnimator 执行下一步动画
mSurfaceAnimator.startAnimation(t, anim, hidden, type, animationFinishedCallback,
animationCancelledCallback, snapshotAnim, mSurfaceFreezer);
}
这三个方法,根据情况,调用任意一个即可开启动画。最终它会把动画交 WindowContainer 的成员变量 SurfaceAnimator mSurfaceAnimator 去执行下一步动画,如下
// SurfaceAnimator.java
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
@AnimationType int type,
@Nullable OnAnimationFinishedCallback animationFinishedCallback,
@Nullable Runnable animationCancelledCallback,
@Nullable AnimationAdapter snapshotAnim, @Nullable SurfaceFreezer freezer) {
cancelAnimation(t, true /* restarting */, true /* forwardCancel */);
mAnimation = anim;
mAnimationType = type;
mSurfaceAnimationFinishedCallback = animationFinishedCallback;
mAnimationCancelledCallback = animationCancelledCallback;
// mAnimatable 就是 WindowContainer
final SurfaceControl surface = mAnimatable.getSurfaceControl();
if (surface == null) {
// ...
}
// 1. 获取 leash
// freezer 就是 WindowContainer 的成员变量 mSurfaceFreezer
mLeash = freezer != null ? freezer.takeLeashForAnimation() : null;
if (mLeash == null) {
// freezer 没有 leashg,就创建毅哥
mLeash = createAnimationLeash(mAnimatable, surface, t, type,
mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), 0 /* x */,
0 /* y */, hidden, mService.mTransactionFactory);
// 2. 通知 WindowContainer leash 创建完成
mAnimatable.onAnimationLeashCreated(t, mLeash);
}
mAnimatable.onLeashAnimationStarting(t, mLeash);
if (mAnimationStartDelayed) {
ProtoLog.i(WM_DEBUG_ANIM, "Animation start delayed for %s", mAnimatable);
return;
}
// 3. 把 leash 交给 AnimationAdapter 去执行动画
mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback);
// ...
}
从整体看,SurfaceAnimator 获取 leash 后,把 leash 交给 AnimationAdapter 去执行动画。
一般来说,leash 都是创建出来的,但是也可能从 WindowContainer#mSurfaceFreezer 中获取。这里看下创建 leash 的过程,如下
// SurfaceAnimator.java
static SurfaceControl createAnimationLeash(Animatable animatable, SurfaceControl surface,
Transaction t, @AnimationType int type, int width, int height, int x, int y,
boolean hidden, Supplier<Transaction> transactionFactory) {
ProtoLog.i(WM_DEBUG_ANIM, "Reparenting to leash for %s", animatable);
final SurfaceControl.Builder builder = animatable.makeAnimationLeash() // 创建 leash
.setParent(animatable.getAnimationLeashParent()) // 设置 parent surface
.setName(surface + " - animation-leash of " + animationTypeToString(type))
.setHidden(hidden)
.setEffectLayer()
.setCallsite("SurfaceAnimator.createAnimationLeash");
final SurfaceControl leash = builder.build();
t.setWindowCrop(leash, width, height);
t.setPosition(leash, x, y);
t.show(leash);
t.setAlpha(leash, hidden ? 0 : 1);
t.reparent(surface, leash); // 把 WindowContainer surface reparent 到 leash 上
return leash;
}
创建 leash 时,它一般是挂载到 WindowContainer 的 parent 之下,并且会把 WindowContainer surface reparent 到 leash 上。为何要创建 leash,因为动画操作的是 leash surface,而不是 WindowContainer surface。
获得 leash 后,会通知 WindowContainer,WindowContainer 会保存 leash,并重新更新 layer,如下
// WindowContainer.java
public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
mLastLayer = -1;
// 保存 leash
mAnimationLeash = leash;
// 通过 parent 重新更新 layer
reassignLayer(t);
// Leash is now responsible for position, so set our position to 0.
resetSurfacePositionForAnimationLeash(t);
}
最后,把 leash 传递给 AnimationAdapter 去执行下一步动画。对于 local animation 来说,AnimationAdapter 是 LocalAnimationAdapter,如下
// LocalAnimationAdapter.java
public void startAnimation(SurfaceControl animationLeash, Transaction t,
@AnimationType int type, @NonNull OnAnimationFinishedCallback finishCallback) {
// 交给 SurfaceAnimationRunner 去真正执行动画
mAnimator.startAnimation(mSpec, animationLeash, t,
() -> finishCallback.onAnimationFinished(type, this));
}
LocalAnimationAdapter 只是一个适配器,它把数据交给 SurfaceAnimationRunner 去执行动画。
// SurfaceAnimationRunner.java
void startAnimation(AnimationSpec a, SurfaceControl animationLeash, Transaction t,
Runnable finishCallback) {
synchronized (mLock) {
// RunningAnimation 就是一个数据包装类
final RunningAnimation runningAnim = new RunningAnimation(a, animationLeash,
finishCallback);
// 一般没有 edge extension
boolean requiresEdgeExtension = requiresEdgeExtension(a);
if (requiresEdgeExtension) {
// ...
}
if (!requiresEdgeExtension) {
// mPendingAnimations 保存即将执行的动画
mPendingAnimations.put(animationLeash, runningAnim);
if (!mAnimationStartDeferred && mPreProcessingAnimations.isEmpty()) {
// 请求 Vsync 信号,执行 startAnimations()
mChoreographer.postFrameCallback(this::startAnimations);
}
}
// Some animations (e.g. move animations) require the initial transform to be
// applied immediately.
applyTransformation(runningAnim, t, 0 /* currentPlayTime */);
}
}
private void startAnimations(long frameTimeNanos) {
synchronized (mLock) {
if (!mPreProcessingAnimations.isEmpty()) {
}
startPendingAnimationsLocked();
}
mPowerManagerInternal.setPowerBoost(Boost.INTERACTION, 0);
}
private void startPendingAnimationsLocked() {
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
startAnimationLocked(mPendingAnimations.valueAt(i));
}
mPendingAnimations.clear();
}
private void startAnimationLocked(RunningAnimation a) {
// 创建 ValueAnimator
final ValueAnimator anim = mAnimatorFactory.makeAnimator();
// Animation length is already expected to be scaled.
anim.overrideDurationScale(1.0f);
anim.setDuration(a.mAnimSpec.getDuration());
// 监听动画每一帧
anim.addUpdateListener(animation -> {
synchronized (mCancelLock) {
if (!a.mCancelled) {
final long duration = anim.getDuration();
long currentPlayTime = anim.getCurrentPlayTime();
if (currentPlayTime > duration) {
currentPlayTime = duration;
}
// 从动画中获取数据,并操作 leash,这些操作保存到 mFrameTransaction
applyTransformation(a, mFrameTransaction, currentPlayTime);
}
}
// 执行 mFrameTransaction
// Transaction will be applied in the commit phase.
scheduleApplyTransaction();
});
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
synchronized (mCancelLock) {
if (!a.mCancelled) {
// TODO: change this back to use show instead of alpha when b/138459974 is
// fixed.
mFrameTransaction.setAlpha(a.mLeash, 1);
}
}
}
// 动画执行完成
@Override
public void onAnimationEnd(Animator animation) {
synchronized (mLock) {
mRunningAnimations.remove(a.mLeash);
synchronized (mCancelLock) {
if (!a.mCancelled) {
mAnimationThreadHandler.post(a.mFinishCallback);
}
}
}
}
});
a.mAnim = anim;
mRunningAnimations.put(a.mLeash, a);
// 启动 ValueAnimator
anim.start();
if (a.mAnimSpec.canSkipFirstFrame()) {
// If we can skip the first frame, we start one frame later.
anim.setCurrentPlayTime(mChoreographer.getFrameIntervalNanos() / NANOS_PER_MS);
}
// Immediately start the animation by manually applying an animation frame. Otherwise, the
// start time would only be set in the next frame, leading to a delay.
anim.doAnimationFrame(mChoreographer.getFrameTime());
}
SurfaceAnimationRunner 就是通过一个 ValueAnimator 动画来操作 leash,从而形成动画。当 ValueAnimator 有 update event 到来时,首先根据 Animation 数据来操作 leash,如下
// SurfaceAnimationRunner.java
// t 为 SurfaceAnimationRunnber#mFrameTransaction
// currentPlayTime 为动画执行的时间点
private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {
a.mAnimSpec.apply(t, a.mLeash, currentPlayTime);
}
SurfaceAnimationRunner 交给 AnimationSpec 来操作 leash,以 WindowAnimationSpec 为例
// WindowAnimationSpec.java
public void apply(Transaction t, SurfaceControl leash, long currentPlayTime) {
final TmpValues tmp = mThreadLocalTmps.get();
tmp.transformation.clear();
// 根据时间 currentPlayTime,从动画 mAnimation 获取数据,保存到 tmp.transformation
mAnimation.getTransformation(currentPlayTime, tmp.transformation);
tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);
// 根据 tmp.transformation,对 leash 进行 rotate、translate、scale、alpha 操作
// 这些操作都保存到 t 中,也就是 SurfaceAnimationRunnber#mFrameTransaction
t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats);
t.setAlpha(leash, tmp.transformation.getAlpha());
// ...
}
SurfaceAnimationRunnber 把 leash 的操作保存到 SurfaceAnimationRunnber#mFrameTransaction 后,然后需要 apply mFrameTransaction ,如下
// SurfaceAnimationRunnber.java
private void scheduleApplyTransaction() {
if (!mApplyScheduled) {
// 请求 Vsync 信号,执行 applyTransaction()
mChoreographer.postCallback(CALLBACK_TRAVERSAL, mApplyTransactionRunnable,
null /* token */);
mApplyScheduled = true;
}
}
private void applyTransaction() {
mFrameTransaction.setAnimationTransaction();
mFrameTransaction.setFrameTimelineVsync(mChoreographer.getVsyncId());
// apply mFrameTransaction
mFrameTransaction.apply();
mApplyScheduled = false;
}
apply mFrameTransaction 就是对 leash 执行操作,因为就看到了 local animation 动画。
当 ValueAnimator 执行完成后,会执行 SurfaceAnimator 的传入的回调
// SurfaceAnimator.java
SurfaceAnimator(Animatable animatable,
@Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback,
WindowManagerService service) {
// 这个就是动画完成的回调
mInnerAnimationFinishedCallback = getFinishedCallback(staticAnimationFinishedCallback);
}
private OnAnimationFinishedCallback getFinishedCallback(
@Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback) {
return (type, anim) -> {
synchronized (mService.mGlobalLock) {
final SurfaceAnimator target = mService.mAnimationTransferMap.remove(anim);
if (target != null) {
target.mInnerAnimationFinishedCallback.onAnimationFinished(type, anim);
return;
}
if (anim != mAnimation) {
return;
}
final Runnable resetAndInvokeFinish = () -> {
// We need to check again if the animation has been replaced with a new
// animation because the animatable may defer to finish.
if (anim != mAnimation) {
return;
}
// 这是调用 WindowContainer#startAnimation() 传入的回调
final OnAnimationFinishedCallback animationFinishCallback =
mSurfaceAnimationFinishedCallback;
// 重置: 把 WindowContainer surface 复位,移除 leash
reset(mAnimatable.getSyncTransaction(), true /* destroyLeash */);
// 通知 WindowContainer 动画执行完成
if (staticAnimationFinishedCallback != null) {
staticAnimationFinishedCallback.onAnimationFinished(type, anim);
}
// 执行 WindowContainer#startAnimation() 传入的回调
if (animationFinishCallback != null) {
animationFinishCallback.onAnimationFinished(type, anim);
}
};
// 如果不推迟动画结束,就直接执行 resetAndInvokeFinish
if (!(mAnimatable.shouldDeferAnimationFinish(resetAndInvokeFinish)
|| anim.shouldDeferAnimationFinish(resetAndInvokeFinish))) {
resetAndInvokeFinish.run();
}
mAnimationFinished = true;
}
};
}
动画结束,只要不被推迟结束,就会先执行 reset,另外还会通知 WindowContainer 和发起方,动画完成。
reset 其实就是对 WindowContainer surface 进行复位,因为在执行动画时,它被 reparent 到 leash。另外,还会移除 leash,如下
// SurfaceAnimator.java
private void reset(Transaction t, boolean destroyLeash) {
mService.mAnimationTransferMap.remove(mAnimation);
mAnimation = null;
mSurfaceAnimationFinishedCallback = null;
mAnimationType = ANIMATION_TYPE_NONE;
final SurfaceFreezer.Snapshot snapshot = mSnapshot;
mSnapshot = null;
if (snapshot != null) {
// Reset the mSnapshot reference before calling the callback to prevent circular reset.
snapshot.cancelAnimation(t, !destroyLeash);
}
if (mLeash == null) {
return;
}
SurfaceControl leash = mLeash;
mLeash = null;
final boolean scheduleAnim = removeLeash(t, mAnimatable, leash, destroyLeash);
mAnimationFinished = false;
// 所有的操作,都是保存到 t 这个 Transaction 中,这里调用动画线程来 apply 这个 transaction
if (scheduleAnim) {
mService.scheduleAnimationLocked();
}
}
static boolean removeLeash(Transaction t, Animatable animatable, @NonNull SurfaceControl leash,
boolean destroy) {
boolean scheduleAnim = false;
final SurfaceControl surface = animatable.getSurfaceControl();
final SurfaceControl parent = animatable.getParentSurfaceControl();
final SurfaceControl curAnimationLeash = animatable.getAnimationLeash();
final boolean reparent = surface != null && (curAnimationLeash == null
|| curAnimationLeash.equals(leash));
if (reparent) {
ProtoLog.i(WM_DEBUG_ANIM, "Reparenting to original parent: %s for %s",
parent, animatable);
// We shouldn't really need these isValid checks but we do
// b/130364451
if (surface.isValid() && parent != null && parent.isValid()) {
// 把 WindowContainer surface reparent 到原本的 parent surface 上
t.reparent(surface, parent);
scheduleAnim = true;
}
}
if (destroy) {
// 移除 leash
t.remove(leash);
scheduleAnim = true;
}
if (reparent) {
// 通知 WindowContainer leash 被移除,WindowContainer 会重新更新 layer 和 surface position
animatable.onAnimationLeashLost(t);
scheduleAnim = true;
}
return scheduleAnim;
}
通知 WindowContainer 和调用方,动画执行完成,需要根据实际情况来分析,这里就不做代码展示。
到此,local animation 就结束了,如果想消化本篇文章,读者需要根据实际情况,进行实际分析,以做到融会贯通。