动画移除流程
动画播放结束后回调函数分析
回调函数的调用过程
在动画播放流程中,SurfaceAnimationRunner.startAnimationLocked方法里,对动画结束通过onAnimationEnd方法进行了监听。
@Override
public void onAnimationEnd(Animator animation) {
synchronized (mLock) {
//从mRunningAnimations这个映射(或字典)中移除与a.mLeash相关的动画。
mRunningAnimations.remove(a.mLeash);
synchronized (mCancelLock) {
if (!a.mCancelled) {
// Post on other thread that we can push final state without jank.
//调用回调函数
mAnimationThreadHandler.post(a.mFinishCallback);
}
}
}
}
mRunningAnimations.remove(a.mLeash);移除动画,后续mAnimationThreadHandler.post(a.mFinishCallback);回调函数。
其中传递的参数a.mFinishCallback,在RunningAnimation构造方法中对mFinishCallback进行了赋值。
RunningAnimation(AnimationSpec animSpec, SurfaceControl leash, Runnable finishCallback) {
mAnimSpec = animSpec;
mLeash = leash;
mFinishCallback = finishCallback;
}
就是SurfaceAnimationRunner.startAnimation方法中的
final RunningAnimation runningAnim = new RunningAnimation(a, animationLeash, finishCallback);
其中的finishCallback是从前面LocalAnimationAdapter.startAnimation方法中传递的() -> finishCallback.onAnimationFinished(type, this),调用这个函数开始动画的结束流程。
@Override
public void startAnimation(SurfaceControl animationLeash, Transaction t,
@AnimationType int type, @NonNull OnAnimationFinishedCallback finishCallback) {
mAnimator.startAnimation(mSpec, animationLeash, t,
() -> finishCallback.onAnimationFinished(type, this));
}
前面说了动画的播放流程,这里我们主要关注移除流程() -> finishCallback.onAnimationFinished(type, this)。
即a.mFinishCallback指的就是() -> finishCallback.onAnimationFinished(type, this)
回调函数的实现
onAnimationFinished(type, this)是OnAnimationFinishedCallback接口中的方法。
代码路径:frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimator.java
/**
* Callback to be passed into {@link AnimationAdapter#startAnimation} to be invoked by the
* component that is running the animation when the animation is finished.
*/
interface OnAnimationFinishedCallback {
void onAnimationFinished(@AnimationType int type, AnimationAdapter anim);
}
这是一个函数式接口,我们来看看这个接口是怎么实现的
finishCallback是OnAnimationFinishedCallback接口对象。结合前面SurfaceAnimator.startAnimation方法中调用的
mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback);
即finishCallback的值就是mInnerAnimationFinishedCallback,这个参数同样是在SurfaceAnimator的构造方法中初始化的。
/**
* @param animatable The object to animate.
* @param staticAnimationFinishedCallback Callback to invoke when an animation has finished
* running.
*/
SurfaceAnimator(Animatable animatable,
@Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback,
WindowManagerService service) {
mAnimatable = animatable;
mService = service;
mStaticAnimationFinishedCallback = staticAnimationFinishedCallback;
mInnerAnimationFinishedCallback = getFinishedCallback(staticAnimationFinishedCallback);
}
-
先来看看
staticAnimationFinishedCallback前面说过在WindowContainer构造方法中初始化mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);从代码中看staticAnimationFinishedCallback传递的是this::onAnimationFinished,onAnimationFinished在WindowContainer中实现 代码路径frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java/** * Called when an animation has finished running. */ protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) { ...... }staticAnimationFinishedCallback.onAnimationFinished其实就是调用WindowContainer.onAnimationFinished方法 -
再来看看
mInnerAnimationFinishedCallback其值是getFinishedCallback(staticAnimationFinishedCallback),即finishCallback实际上就是getFinishedCallback(staticAnimationFinishedCallback)代码路径:frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimator.javaprivate OnAnimationFinishedCallback getFinishedCallback( @Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback) { return (type, anim) -> { ...... }; }getFinishedCallback方法中实现了onAnimationFinished方法
() -> finishCallback.onAnimationFinished(type, this)中onAnimationFinished(type, this)方法的实现,就是对应的是SurfaceAnimator.getFinishedCallback方法中的(type, anim) -> {......}。
从上述代码中我们发现,如果回调参数的值是从WindowContainer传递过来的,那么就是是调用的WindowContainer.onAnimationFinished方法(如:this::onAnimationFinished对应的变量staticAnimationFinishedCallback调用的onAnimationFinished方法);
而在其他情况调用的onAnimationFinished方法,是调用SurfaceAnimator.getFinishedCallback方法中的(type, anim) -> {......}。
下面我们来看看SurfaceAnimator.getFinishedCallback方法。
回调处理动画完成的逻辑
SurfaceAnimator.getFinishedCallback() 代码路径:frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimator.java
private OnAnimationFinishedCallback getFinishedCallback(
@Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback) {
return (type, anim) -> {
synchronized (mService.mGlobalLock) {
//移除AnimationAdapter对应的SurfaceAnimator,并将这个SurfaceAnimator返回给target
//mAnimationTransferMap属于启动窗口的动画场景,这里我们不涉及
final SurfaceAnimator target = mService.mAnimationTransferMap.remove(anim);
if (target != null) {
//递归调用onAnimationFinished(type, anim),即return (type, anim) -> {......}
//直到所有的SurfaceAnimator移除完
target.mInnerAnimationFinishedCallback.onAnimationFinished(type, anim);
return;
}
//检查动画是否已被新动画替换,如果当前动画 (anim) 不等于之前存储的动画 (mAnimation),则不执行后续操作
if (anim != mAnimation) {
return;
}
//定义一个名为 resetAndInvokeFinish 的 Runnable
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;
}
//mSurfaceAnimationFinishedCallback是在WindowContainer.startAnimation中赋值的
//其传递值为null,最终SurfaceAnimator.startAnimation赋值给mSurfaceAnimationFinishedCallback
final OnAnimationFinishedCallback animationFinishCallback =
mSurfaceAnimationFinishedCallback;
//重置与动画相关的状态
reset(mAnimatable.getSyncTransaction(), true /* destroyLeash */);
//WindowContainer构造方法中给SurfaceAnimator构造方法传递了staticAnimationFinishedCallback
if (staticAnimationFinishedCallback != null) {
//当一个Surface上的动画结束或取消且不重新启动时,这个回调将被执行。
//这是一个静态回调,它对通过这个 SurfaceAnimator 启动的所有动画都有效。
//回调WindowContainer.onAnimationFinished方法
staticAnimationFinishedCallback.onAnimationFinished(type, anim);
}
//mSurfaceAnimationFinishedCallback的值为null,因此animationFinishCallback的值为null
if (animationFinishCallback != null) {
//当一个Surface上的动画结束或取消且不重新启动时,这个回调将被执行。
//这个回调是每个动画(即每个 AnimationAdapter)特有的。
//如果在WindowContainer.startAnimation方法中有赋值,
//则回调WindowContainer.onAnimationFinished方法
animationFinishCallback.onAnimationFinished(type, anim);
}
};
// If both the Animatable and AnimationAdapter requests to be deferred, only the
// first one will be called.
//如果 mAnimatable 或动画本身请求延迟动画完成,并且它们都没有被延迟,
//那么直接执行 resetAndInvokeFinish.run()。否则,延迟执行。
if (!(mAnimatable.shouldDeferAnimationFinish(resetAndInvokeFinish)
|| anim.shouldDeferAnimationFinish(resetAndInvokeFinish))) {
resetAndInvokeFinish.run();
}
//设置动画完成标志,将 mAnimationFinished 设置为 true
mAnimationFinished = true;
}
};
}
这个方法主要做了这几件事:
- 通过递归的方式移除所有AnimationAdapter对应的SurfaceAnimator
其中的mAnimationTransferMap在启动窗口流程中,ActivityRecord.addStartingWindow中有调用transferStartingWindow方法,逐步调用到SurfaceAnimator.transferAnimation中进行添加
mService.mAnimationTransferMap.put(mAnimation, this);,这里我们不涉及,因此target的值为null - 使用
shouldDeferAnimationFinish方法(默认返回false)用来判断是否需要延迟完成动画 - 执行
resetAndInvokeFinish.run(),调用reset(mAnimatable.getSyncTransaction(), true /* destroyLeash */);重置动画相关状态 - 最后调用回调通过
staticAnimationFinishedCallback.onAnimationFinished(type, anim);,调用WindowContainer.onAnimationFinished方法处理和响应动画完成的逻辑
重置动画相关状态并移除leash
reset(mAnimatable.getSyncTransaction(), true /* destroyLeash */);
代码路径:frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimator.java
private void reset(Transaction t, boolean destroyLeash) {
//移除AnimationAdapter对应的SurfaceAnimator
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.
//如果有屏幕冻结时的快照,取消该动画。
//最终会调用到SurfaceAnimationRunner.onAnimationCancelled
snapshot.cancelAnimation(t, !destroyLeash);
}
if (mLeash == null) {
return;
}
//使用leash存储动画图层mLeash
SurfaceControl leash = mLeash;
//把动画图层置为空
mLeash = null;
//移除leash
final boolean scheduleAnim = removeLeash(t, mAnimatable, leash, destroyLeash);
//将mAnimationFinished设置为false
mAnimationFinished = false;
if (scheduleAnim) {
//leash成功移除后,在WMS中会通过WindowAnimator调度动画,协调各个窗口
mService.scheduleAnimationLocked();
}
}
移除leash
调用removeLeash方法移除leash
final boolean scheduleAnim = removeLeash(t, mAnimatable, leash, destroyLeash);
传递的mAnimatable表示当前窗口,leash就是动画图层,destroyLeash在前面getFinishedCallback流程中传递的值为true
static boolean removeLeash(Transaction t, Animatable animatable, @NonNull SurfaceControl leash,
boolean destroy) {
/* log add start*/
Slog.i("WindowManager:","removeLeash leash = " + leash , new Exception());
/* log add end*/
//scheduleAnim一个标志位,初始值为false
//为true时,走前面reset方法中的mService.scheduleAnimationLocked()流程
boolean scheduleAnim = false;
//获取当前窗口的SurfaceControl
final SurfaceControl surface = animatable.getSurfaceControl();
//获取当前窗口的父窗口的SurfaceControl
final SurfaceControl parent = animatable.getParentSurfaceControl();
//获取动画图层
final SurfaceControl curAnimationLeash = animatable.getAnimationLeash();
// If the surface was destroyed or the leash is invalid, we don't care to reparent it back.
// Note that we also set this variable to true even if the parent isn't valid anymore, in
// order to ensure onAnimationLeashLost still gets called in this case.
// If the animation leash is set, and it is different from the removing leash, it means the
// surface now has a new animation surface. We don't want to reparent for that.
//1.surface不为空
//2.curAnimationLeash不为空,且curAnimationLeash等于leash
//因此reparent值为true
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
//判断当前窗口的surface是否有效,以及该窗口的父窗口的图层不为空且有效
if (surface.isValid() && parent != null && parent.isValid()) {
//把当前窗口图层和其父窗口的图层重新建立父子关系
t.reparent(surface, parent);
//scheduleAnim置为true
scheduleAnim = true;
}
}
//destroy传递过来值为true
if (destroy) {
//移除图层
t.remove(leash);
//scheduleAnim置为true
scheduleAnim = true;
}
if (reparent) {
// Make sure to inform the animatable after the surface was reparented (or reparent
// wasn't possible, but we still need to invoke the callback)
//1.移除和leash相关联的窗口和surface(这个只在前面requiresEdgeExtension为true时逻辑中有涉及)
//2.调整surface
animatable.onAnimationLeashLost(t);
//scheduleAnim置为true
scheduleAnim = true;
}
return scheduleAnim;
}
-
获取当前窗口的图层
final SurfaceControl surface = animatable.getSurfaceControl();代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java/** * @return The SurfaceControl for this container. * The SurfaceControl must be valid if non-null. */ @Override public SurfaceControl getSurfaceControl() { return mSurfaceControl; }直接返回一个SurfaceControl。
-
获取当前窗口父窗口的图层 代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
/* * @return The SurfaceControl parent for this containers SurfaceControl. * The SurfaceControl must be valid if non-null. */ @Override public SurfaceControl getParentSurfaceControl() { final WindowContainer parent = getParent(); if (parent == null) { return null; } return parent.getSurfaceControl(); } @Override final protected WindowContainer getParent() { return mParent; }先获取当前窗口的父窗口,在获取父窗口的SurfaceControl。
-
获取动画图层 代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
@Override public SurfaceControl getAnimationLeash() { return mAnimationLeash; }mAnimationLeash是前面SurfaceAnimator的startAnimation方法中的mAnimatable.onAnimationLeashCreated(t, mLeash);,把mLeash赋值给了mAnimationLeash,因此这个方法获取的是动画图层。 -
当前窗口图层和其父窗口的图层重新建立父子关系
t.reparent(surface, parent);test-window的SurfaceControl重新认WindowToken的SurfaceControl为父。 代码路径:frameworks/base/core/java/android/view/SurfaceControl.java/** * Re-parents a given layer to a new parent. Children inherit transform (position, scaling) * crop, visibility, and Z-ordering from their parents, as if the children were pixels within the * parent Surface. * * @param sc The SurfaceControl to reparent * @param newParent The new parent for the given control. * @return This Transaction */ @NonNull public Transaction reparent(@NonNull SurfaceControl sc, @Nullable SurfaceControl newParent) { //检查传入的SurfaceControl对象是否满足某些预设条件 checkPreconditions(sc); long otherObject = 0; if (newParent != null) { //检查新父对象是否被释放。如果已经被释放,那么它会抛出异常。 newParent.checkNotReleased(); //新父对象不为null且未被释放,那么将新父对象的Native对象赋值给otherObject。 otherObject = newParent.mNativeObject; } //传入了三个参数:1.当前对象的Native对象 2.被重新设置父对象的SurfaceControl的Native对象 3.新父对象的Native对象。 //用于实现重新设置父对象的具体操作。 nativeReparent(mNativeObject, sc.mNativeObject, otherObject); //把被重新设置父对象的SurfaceControl和新父对象存储到mReparentedSurfaces这个map中。 mReparentedSurfaces.put(sc, newParent); return this; }前面说过
reparent方法中通过mReparentedSurfaces这个ArrayMap临时存储父子关系,key值存储SurfaceControl对象,value为其父SurfaceControl对象,此时mReparentedSurfaces的键值对为: key:Surface(name=8aabddb test-window)/@0x1038e9a(当前窗口的SurfaceControl) value:Surface(name=WindowToken{15f96ea type=2038 android.os.BinderProxy@1d0fed5})/@0xc7312c1(当前窗口的父窗口的SurfaceControl,即WindowToken的SurfaceControl) 此时leash还没有被释放,WindowToken的SurfaceControl有两个儿子SurfaceControl,关系如下图所示:此时leash逐渐发现不对劲,但是假装不知道 假如我们后面不执行移除leash图层的操作,那么这个图层一直会保持这个状态挂在WindowToken上和test-window共享父亲。
-
移除动画图层
t.remove(leash);/** * Equivalent to reparent with a null parent, in that it removes * the SurfaceControl from the scene, but it also releases * the local resources (by calling {@link SurfaceControl#release}) * after this method returns, {@link SurfaceControl#isValid} will return * false for the argument. * * @param sc The surface to remove and release. * @return This transaction * @hide */ @NonNull public Transaction remove(@NonNull SurfaceControl sc) { reparent(sc, null); sc.release(); return this; }同样调用了
reparent方法,先把需要remove的图层的父图层置空,然后释放。 此时mReparentedSurfaces的键值对为: key:Surface(name=8aabddb test-window)/@0x1038e9a(当前窗口的SurfaceControl) value:Surface(name=WindowToken{15f96ea type=2038 android.os.BinderProxy@1d0fed5})/@0xc7312c1(WindowToken的SurfaceControl) 和 key:Surface(name=Surface(name=8aabddb test-window)/@0x1038e9a - animation-leash of window_animation)/@0x38e37a8(动画图层leash) value:null过程如下所示:leash:原来我才是多余的那个,悠悠苍天,何薄于我!
-
移除和leash相关联的窗口和surface并调整surface
animatable.onAnimationLeashLost(t);代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java@Override public void onAnimationLeashLost(Transaction t) { mLastLayer = -1; //调用mWmService中的mSurfaceAnimationRunner对象的onAnimationLeashLost方法 //用于移除和leash相关联的窗口,这个只在前面requiresEdgeExtension为true时逻辑中有涉及 mWmService.mSurfaceAnimationRunner.onAnimationLeashLost(mAnimationLeash, t); //mAnimationLeash置为空 mAnimationLeash = null; mNeedsZBoost = false; //调整其所有child的z-order reassignLayer(t); //更新Surface位置 updateSurfacePosition(t); }其中
mWmService.mSurfaceAnimationRunner.onAnimationLeashLost(mAnimationLeash, t);的mAnimationLeash前面说过就是动画图层。这个只在前面SurfaceAnimationRunner的startAnimation方法中requiresEdgeExtension为true时逻辑中有涉及,其为true时才会操作mEdgeExtensions这个ArrayList,这里不讨论。
协调动画显示
在SurfaceAnimator.reset()方法最后调用了mService.scheduleAnimationLocked();
代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
void scheduleAnimationLocked() {
mAnimator.scheduleAnimation();
}
void scheduleAnimation() {
if (!mAnimationFrameCallbackScheduled) {
//mAnimationFrameCallbackScheduled 设置为 true,表示动画帧回调已经安排
mAnimationFrameCallbackScheduled = true;
//每一帧被绘制时,回调mAnimationFrameCallback
mChoreographer.postFrameCallback(mAnimationFrameCallback);
}
}
和前面显示动画的流程一样有调用WindowAnimator的scheduleAnimation()方法,协调动画和窗口的显示。
处理和响应动画完成的逻辑
WindowContainer.onAnimationFinished方法 代码路径frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
/**
* 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;
}
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);
}
}
mSurfaceAnimationSources的值是在applyAnimationUnchecked方法中添加的,我们这里不属于远程动画流程,不涉及。
在ActivityRecord和WindowState中都重写了这个方法。我们这里是窗口动画,所以看看WindowState中的逻辑。
@Override
protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
super.onAnimationFinished(type, anim);
mWinAnimator.onAnimationFinished();
}
先调用了父类前面WindowContainer中的onAnimationFinished,然后调用了WindowStateAnimator的onAnimationFinished方法。 代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java
void onAnimationFinished() {
// Done animating, clean up.
ProtoLog.v(WM_DEBUG_ANIM, "Animation done in %s: exiting=%b, reportedVisible=%b",
this, mWin.mAnimatingExit,
(mWin.mActivityRecord != null && mWin.mActivityRecord.reportedVisible));
//检查窗口可见性变化的flag
mWin.checkPolicyVisibilityChange();
final DisplayContent displayContent = mWin.getDisplayContent();
//判断窗口类型为状态栏或通知栏的所有可见性标志位是否为true
if ((mAttrType == LayoutParams.TYPE_STATUS_BAR
|| mAttrType == LayoutParams.TYPE_NOTIFICATION_SHADE) && mWin.isVisibleByPolicy()) {
// Upon completion of a not-visible to visible status bar animation a relayout is
// required.
//设置mLayoutNeeded标志位为true
displayContent.setLayoutNeeded();
}
//处理动画结束后窗口及其子窗口的状态更新和资源清理
mWin.onExitAnimationDone();
//将 displayContent 的 pendingLayoutChanges 标志设置为 FINISH_LAYOUT_REDO_ANIM
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
//如果窗口是壁纸的目标
if (displayContent.mWallpaperController.isWallpaperTarget(mWin)) {
//将 pendingLayoutChanges 标志设置为 FINISH_LAYOUT_REDO_WALLPAPER
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
}
if (DEBUG_LAYOUT_REPEATS) {
mService.mWindowPlacerLocked.debugLayoutRepeats(
"WindowStateAnimator", displayContent.pendingLayoutChanges);
}
if (mWin.mActivityRecord != null) {
//更新窗口对应的应用的可见性
mWin.mActivityRecord.updateReportedVisibilityLocked();
}
}
总结
至此动画从添加到移除的逻辑梳理完成,我们可以发现简单概括就起来动画的显示流程就是: 在窗口添加或移除时,添加动画,新增leash图层在当前窗口和其对应WindowToken之间,调整显示层级关系;播放完动画后,移除动画,移除leash图层,再次调整显示层级关系。
其他补充
SurfaceControl
Surface和SurfaceControl的关系是,Surface是图形生产者和图像消费之间传递数据的缓冲区,而SurfaceControl是Surface的控制类,可以实现复杂的Surface操作,如改变位置、缩放、剪切、透明度以及Z序等。所以当我们需要对某个Surface操作时,只需要修改其SurfaceControl即可。
代码位置:frameworks/base/core/java/android/view/SurfaceControl.java Surface相关的控制方法都在这里
创建图层
SurfaceControl.Builder的build()方法用于创建图层
/**
* Builder class for {@link SurfaceControl} objects.
*
* By default the surface will be hidden, and have "unset" bounds, meaning it can
* be as large as the bounds of its parent if a buffer or child so requires.
*
* It is necessary to set at least a name via {@link Builder#setName}
*/
public static class Builder {
private SurfaceSession mSession;
private int mFlags = HIDDEN;
private int mWidth;
private int mHeight;
private int mFormat = PixelFormat.OPAQUE;
private String mName;
private WeakReference<View> mLocalOwnerView;
private SurfaceControl mParent;
private SparseIntArray mMetadata;
private String mCallsite = "SurfaceControl.Builder";
/**
* Begin building a SurfaceControl with a given {@link SurfaceSession}.
*
* @param session The {@link SurfaceSession} with which to eventually construct the surface.
* @hide
*/
public Builder(SurfaceSession session) {
mSession = session;
}
/**
* Begin building a SurfaceControl.
*/
public Builder() {
}
/**
* Construct a new {@link SurfaceControl} with the set parameters. The builder
* remains valid.
*/
@NonNull
public SurfaceControl build() {
if (mWidth < 0 || mHeight < 0) {
throw new IllegalStateException(
"width and height must be positive or unset");
}
if ((mWidth > 0 || mHeight > 0) && (isEffectLayer() || isContainerLayer())) {
throw new IllegalStateException(
"Only buffer layers can set a valid buffer size.");
}
if ((mFlags & FX_SURFACE_MASK) == FX_SURFACE_NORMAL) {
setBLASTLayer();
}
return new SurfaceControl(
mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata,
mLocalOwnerView, mCallsite);
}
......
}
移除图层
SurfaceControl.Transaction的remove()方法用于移除图层
/**
* An atomic set of changes to a set of SurfaceControl.
*/
public static class Transaction implements Closeable, Parcelable {
......
/**
* Equivalent to reparent with a null parent, in that it removes
* the SurfaceControl from the scene, but it also releases
* the local resources (by calling {@link SurfaceControl#release})
* after this method returns, {@link SurfaceControl#isValid} will return
* false for the argument.
*
* @param sc The surface to remove and release.
* @return This transaction
* @hide
*/
@NonNull
public Transaction remove(@NonNull SurfaceControl sc) {
reparent(sc, null);
sc.release();
return this;
}
......
}
修改图层父子关系
SurfaceControl.Transaction的reparent()方法用于修改图层父子关系
/**
* Re-parents a given layer to a new parent. Children inherit transform (position, scaling)
* crop, visibility, and Z-ordering from their parents, as if the children were pixels within the
* parent Surface.
*
* @param sc The SurfaceControl to reparent
* @param newParent The new parent for the given control.
* @return This Transaction
*/
@NonNull
public Transaction reparent(@NonNull SurfaceControl sc,
@Nullable SurfaceControl newParent) {
//检查传入的SurfaceControl对象是否满足某些预设条件
checkPreconditions(sc);
long otherObject = 0;
if (newParent != null) {
//检查新父对象是否被释放。如果已经被释放,那么它会抛出异常。
newParent.checkNotReleased();
//新父对象不为null且未被释放,那么将新父对象的Native对象赋值给otherObject。
otherObject = newParent.mNativeObject;
}
//传入了三个参数:1.当前对象的Native对象 2.被重新设置父对象的SurfaceControl的Native对象 3.新父对象的Native对象。
//用于实现重新设置父对象的具体操作。
nativeReparent(mNativeObject, sc.mNativeObject, otherObject);
//把被重新设置父对象的SurfaceControl和新父对象存储到mReparentedSurfaces这个map中。
mReparentedSurfaces.put(sc, newParent);
return this;
}
简单聊聊Choreographer
Choreographer扮演 Android 渲染链路中承上启下的角色
承上:负责接收和处理 App 的各种更新消息和回调,等到 Vsync(垂直同步) 到来的时候统一处理。比如集中处理 Input(主要是 Input 事件的处理) 、Animation(动画相关)、Traversal(包括 measure、layout、draw 等操作) ,判断卡顿掉帧情况,记录 CallBack 耗时等
启下:负责请求和接收 Vsync 信号。接收 Vsync 事件回调(通过 FrameDisplayEventReceiver.onVsync );请求 Vsync(FrameDisplayEventReceiver.scheduleVsync)
我们这里mChoreographer.postFrameCallback(this::startAnimations);其实就是先请求Vsync信号,然后接收到Vsync信号回调this::startAnimations。
Choreographer的postFrameCallback和postCallback在处理方式和使用场景上有所不同。
Choreographer的postFrameCallback主要用于在下一个frame渲染时控制执行某些操作,例如View的绘制流程。这个方法会在下一个Vsync信号来临时,遍历CallbackQuenes中的链表,并执行对应的回调方法。这个方法主要在ViewRootImpl中使用,用于分发处理NativeInputQueue的消息回调。
而Choreographer的postCallback则是一个更通用的回调方法,它允许在UI线程中安排一个回调。这个方法可以接受Runnable对象作为参数,该对象定义了回调时要执行的任务。postCallback方法可以在任何需要延迟执行任务或异步处理任务的情况下使用,而不仅仅是在渲染帧时。
总的来说,postFrameCallback更专注于在特定时间点(如渲染帧时)执行特定任务,而postCallback则提供了一种更通用的方式来安排回调,可以在任何需要的时候使用。