接着前文分析Android T 远程动画显示流程其二
我们通过IRemoteAnimationRunner跨进程通信从系统进程来到了桌面进程,这里是真正动画播放的逻辑。
进入桌面进程启动动画
跨进程通信,实现IRemoteAnimationRunner
代码路径:frameworks/base/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
public abstract class RemoteAnimationRunnerCompat extends IRemoteAnimationRunner.Stub {
public abstract void onAnimationStart(@WindowManager.TransitionOldType int transit,
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
RemoteAnimationTarget[] nonApps, Runnable finishedCallback);
@Override
public final void onAnimationStart(@TransitionOldType int transit,
RemoteAnimationTarget[] apps,
RemoteAnimationTarget[] wallpapers,
RemoteAnimationTarget[] nonApps,
final IRemoteAnimationFinishedCallback finishedCallback) {
//调用自身抽象方法onAnimationStart
onAnimationStart(transit, apps, wallpapers,
nonApps, () -> {
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
Log.e("ActivityOptionsCompat", "Failed to call app controlled animation"
+ " finished callback", e);
}
});
}
......
}
这里传递的参数都是前面RemoteAnimationController.goodToGo方法中获取的值。
transit的值是TRANSIT_OLD_WALLPAPER_CLOSE(12);
app指的是桌面和应用的RemoteAnimationTarget;
wallpapers壁纸的RemoteAnimationTarget;
nonApp非APP类型的RemoteAnimationTarget;
finishedCallback是FinishedCallback对象,这里传递的是调用了其onAnimationFinished()方法。
这方方法调用了自身抽象方法调用自身抽象方法onAnimationStart,onAnimationStart方法真正的实现在LauncherAnimationRunner类中
@TargetApi(Build.VERSION_CODES.P)
public class LauncherAnimationRunner extends RemoteAnimationRunnerCompat {
......
@BinderThread
public void onAnimationStart(
int transit,
RemoteAnimationTarget[] appTargets,
RemoteAnimationTarget[] wallpaperTargets,
RemoteAnimationTarget[] nonAppTargets,
Runnable runnable) {
Runnable r = () -> {
//退出动画的流程,此时mAnimationResult为空,尚未进入该流程
finishExistingAnimation();
//创建AnimationResult,传递了两个runnable
//() -> mAnimationResult = null,把AnimationResult对象置空
//runnable,就是前面传递的IRemoteAnimationFinishedCallback.onAnimationFinished
mAnimationResult = new AnimationResult(() -> mAnimationResult = null, runnable);
//传递从系统侧调用过来的参数创建动画
getFactory().onCreateAnimation(transit, appTargets, wallpaperTargets, nonAppTargets,
mAnimationResult);
};
//根据mStartAtFrontOfQueue的值,执行线程 r
if (mStartAtFrontOfQueue) {
//将Runnable插入到消息队列的前面,以确保它尽快被执行
postAtFrontOfQueueAsynchronously(mHandler, r);
} else {
//将Runnable异步地插入到消息队列中,它将在队列中的其他消息之后执行。
postAsyncCallback(mHandler, r);
}
}
......
}
退出动画的流程
finishExistingAnimation();@UiThread private void finishExistingAnimation() { if (mAnimationResult != null) { mAnimationResult.finish(); mAnimationResult = null; } }根据mAnimationResult是否为空执行finish方法,主要就是执行
mASyncFinishRunnable,后续会在动画退出流程中细讲。创建AnimationResult
mAnimationResult = new AnimationResult(() -> mAnimationResult = null, runnable);public static final class AnimationResult { ...... private AnimationResult(Runnable syncFinishRunnable, Runnable asyncFinishRunnable) { mSyncFinishRunnable = syncFinishRunnable; mASyncFinishRunnable = asyncFinishRunnable; } ...... }AnimationResult主要用来返回当前动画播放结果,以便后续执行动画播放完成时的回调(mASyncFinishRunnable)。
() -> mAnimationResult = null,一个把AnimationResult对象置空的Runnable,保存到mSyncFinishRunnable中;
runnable,就是前面传递的IRemoteAnimationFinishedCallback.onAnimationFinished,保存到mASyncFinishRunnable中。传递从系统侧创建的参数创建动画
getFactory().onCreateAnimation(transit, appTargets, wallpaperTargets, nonAppTargets, mAnimationResult);传递了从系统侧创建的参数,并传递了
mAnimationResult对象。这里调用的是RemoteAnimationFactory接口中的onCreateAnimation方法。/** * Used with LauncherAnimationRunner as an interface for the runner to call back to the * implementation. */ @FunctionalInterface public interface RemoteAnimationFactory { /** * Called on the UI thread when the animation targets are received. The implementation must * call {@link AnimationResult#setAnimation} with the target animation to be run. */ void onCreateAnimation(int transit, RemoteAnimationTarget[] appTargets, RemoteAnimationTarget[] wallpaperTargets, RemoteAnimationTarget[] nonAppTargets, LauncherAnimationRunner.AnimationResult result); ...... }RemoteAnimationFactory的实现在QuickstepTransitionManager中。
传递从系统侧创建的参数创建动画
代码路径:packages/apps/Launcher3/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
动画移除流程
处理和响应动画完成的逻辑
代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
private void doAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
for (int i = 0; i < mSurfaceAnimationSources.size(); ++i) {
//mSurfaceAnimationSources中每个容器,做对应的onAnimationFinished
mSurfaceAnimationSources.valueAt(i).onAnimationFinished(type, anim);
}
//清除动画源列表
mSurfaceAnimationSources.clear();
if (mDisplayContent != null) {
//调用DisplayContent的onWindowAnimationFinished方法
//从当前源码上看,主要是针对输入法相关做了一些操作
mDisplayContent.onWindowAnimationFinished(this, type);
}
}
/**
* Called when an animation has finished running.
*/
protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
//主要用于 清空 mSurfaceAnimationSources 列表
doAnimationFinished(type, anim);
//WindowManagerService中实现onAnimationFinished()
//用于唤醒所有等待mGlobalLock对象的线程,确保多个线程能够正确地执行任务
mWmService.onAnimationFinished();
//将 mNeedsZBoost 设置为 false,表示不再需要Z轴增强
mNeedsZBoost = false;
}
我们这里mSurfaceAnimationSources是保存的是需要做动画的ActivityRecord,mSurfaceAnimationSources的值是在applyAnimationUnchecked方法中添加的。
mSurfaceAnimationSources.valueAt(i).onAnimationFinished(type, anim);调用了不同容器onAnimationFinished方法,在ActivityRecord和WindowState中都重写了这个方法。我们这里是远程动画,主要调用的就是ActivityRecord中重写的onAnimationFinished方法。
代码路径:frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
@Override
protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
super.onAnimationFinished(type, anim);
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AR#onAnimationFinished");
mTransit = TRANSIT_OLD_UNSET;
mTransitFlags = 0;
setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
"ActivityRecord");
clearThumbnail();
setClientVisible(isVisible() || mVisibleRequested);
getDisplayContent().computeImeTargetIfNeeded(this);
ProtoLog.v(WM_DEBUG_ANIM, "Animation done in %s"
+ ": reportedVisible=%b okToDisplay=%b okToAnimate=%b startingDisplayed=%b",
this, reportedVisible, okToDisplay(), okToAnimate(),
isStartingWindowDisplayed());
// clean up thumbnail window
if (mThumbnail != null) {
mThumbnail.destroy();
mThumbnail = null;
}
// 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);
// The starting window could transfer to another activity after app transition started, in
// that case the latest top activity might not receive exit animation done callback if the
// starting window didn't applied exit animation success. Notify animation finish to the
// starting window if needed.
if (task != null && startingMoved) {
final WindowState transferredStarting = task.getWindow(w ->
w.mAttrs.type == TYPE_APPLICATION_STARTING);
if (transferredStarting != null && transferredStarting.mAnimatingExit
&& !transferredStarting.isSelfAnimating(0 /* flags */,
ANIMATION_TYPE_WINDOW_ANIMATION)) {
transferredStarting.onExitAnimationDone();
}
}
getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
scheduleAnimation();
// Schedule to handle the stopping and finishing activities which the animation is done
// because the activities which were animating have not been stopped yet.
mTaskSupervisor.scheduleProcessStoppingAndFinishingActivitiesIfNeeded();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}