前言
Android 16系统源码_窗口动画(一)窗口过渡动画层级图分析这篇文章我们有分析过,系统触发窗口显示和移除动画的过程中,都会创建一个leash图层。
Android 16系统源码_窗口动画(二)窗口显示动画源码调用流程这篇文章我们具体分析了系统触发窗口显示动画的过程中,leash图层的创建流程。
本篇文章我们将会结合源码具体来分析下系统触发窗口移除动画的过程中,leash图层的创建流程。
一 创建leash图层的代码源头
1.1 查找创建leash图层的代码源头
触发窗口移除动画时候的SurfaceFlinger图层信息如下所示。
在叶子节点下回多了一个含有animation-leash关键字的Surface图层,结合Android 16系统源码_窗口动画(二)窗口显示动画源码调用流程这篇文章我们知道,可以定位到SurfaceAnimator这个类的394行。
/base/services/core/java/com/android/server/wm/SurfaceAnimator.java:394: .setName(surface + " - animation-leash of " + animationTypeToString(type))
class SurfaceAnimator {
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) {
if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to leash");
final SurfaceControl.Builder builder = animatable.makeAnimationLeash()
.setParent(animatable.getAnimationLeashParent())
.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);
return leash;
}
}
二 创建leash图层的源码流程
2.1 createAnimationLeash方法调用流程
2.1.1 堆栈信息
窗口被移除时候通过断点调试可以得到SurfaceAnimator的createAnimationLeash方法的调用堆栈信息。
2.1.2 createAnimationLeash方法源码调用流程
结合以上方法调用栈,在系统源码中进行定位可以得到以下调用流程
//frameworks/base/services/core/java/com/android/server/wm/Session.java
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
final WindowManagerService mService;
@Override
public void remove(IWindow window) {
mService.removeWindow(this, window);
}
}
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
void removeWindow(Session session, IWindow client) {
WindowState win = windowForClientLocked(session, client, false);
if (win != null) {
win.removeIfPossible();
return;
}
win.removeIfPossible();
...代码省略...
}
}
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState,
InsetsControlTarget, InputTarget {
@Override
void removeIfPossible() {
super.removeIfPossible();
removeIfPossible(false /*keepVisibleDeadWindow*/);
}
final WindowStateAnimator mWinAnimator;
private void removeIfPossible(boolean keepVisibleDeadWindow) {
...代码省略...
mWinAnimator.applyAnimationLocked(transit, false)
...代码省略...
}
}
class WindowStateAnimator {
boolean applyAnimationLocked(int transit, boolean isEntrance) {
if (mWin.isAnimating() && mAnimationIsEntrance == isEntrance) {
// If we are trying to apply an animation, but already running
// an animation of the same type, then just leave that one alone.
return true;
}
final boolean isImeWindow = mWin.mAttrs.type == TYPE_INPUT_METHOD;
if (isEntrance && isImeWindow) {
mWin.getDisplayContent().adjustForImeIfNeeded();
mWin.setDisplayLayoutNeeded();
mService.mWindowPlacerLocked.requestTraversal();
}
if (mWin.mToken.okToAnimate()) {
int anim = mWin.getDisplayContent().getDisplayPolicy().selectAnimation(mWin, transit);
int attr = -1;
Animation a = null;
if (anim != DisplayPolicy.ANIMATION_STYLEABLE) {
if (anim != DisplayPolicy.ANIMATION_NONE) {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#loadAnimation");
a = AnimationUtils.loadAnimation(mContext, anim);
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
} else {
switch (transit) {
case WindowManagerPolicy.TRANSIT_ENTER:
attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
break;
case WindowManagerPolicy.TRANSIT_EXIT:
attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
break;
case WindowManagerPolicy.TRANSIT_SHOW:
attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
break;
case WindowManagerPolicy.TRANSIT_HIDE:
attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
break;
}
if (attr >= 0) {
a = mWin.getDisplayContent().mAppTransition.loadAnimationAttr(
mWin.mAttrs, attr, TRANSIT_OLD_NONE);
}
}
if (DEBUG_ANIM) Slog.v(TAG,
"applyAnimation: win=" + this
+ " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
+ " a=" + a
+ " transit=" + transit
+ " type=" + mAttrType
+ " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
if (a != null) {
if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#startAnimation");
mWin.startAnimation(a);
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
mAnimationIsEntrance = isEntrance;
}
} else if (!isImeWindow) {
mWin.cancelAnimation();
}
if (!isEntrance && isImeWindow) {
mWin.getDisplayContent().adjustForImeIfNeeded();
}
return mWin.isAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION);
}
}
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState,
InsetsControlTarget, InputTarget {
void startAnimation(Animation anim) {
...代码省略...
final AnimationAdapter adapter = new LocalAnimationAdapter(
new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */,
0 /* windowCornerRadius */),
mWmService.mSurfaceAnimationRunner);
startAnimation(getPendingTransaction(), adapter);
commitPendingTransaction();
}
private void startAnimation(Transaction t, AnimationAdapter adapter) {
//继续调用父类WindowContainer的startAnimation方法
startAnimation(t, adapter, mWinAnimator.mLastHidden, ANIMATION_TYPE_WINDOW_ANIMATION);
}
}
//frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable {
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);
// TODO: This should use isVisible() but because isVisible has a really weird meaning at
// the moment this doesn't work for all animatable window containers.
//调用SurfaceAnimator的startAnimation方法
mSurfaceAnimator.startAnimation(t, anim, hidden, type, animationFinishedCallback,
animationCancelledCallback, snapshotAnim);
}
}
class SurfaceAnimator {
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
@AnimationType int type,
@Nullable OnAnimationFinishedCallback animationFinishedCallback,
@Nullable Runnable animationCancelledCallback,
@Nullable AnimationAdapter snapshotAnim, @Nullable SurfaceFreezer freezer) {
...代码省略...
final SurfaceControl surface = mAnimatable.getSurfaceControl();
if (surface == null) {
Slog.w(TAG, "Unable to start animation, surface is null or no children.");
cancelAnimation();
return;
}
if (mLeash == null) {
mLeash = createAnimationLeash(mAnimatable, surface, t, type,
mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), 0 /* x */,
0 /* y */, hidden, mService.mTransactionFactory);
mAnimatable.onAnimationLeashCreated(t, mLeash);
}
...代码省略...
}
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()
.setParent(animatable.getAnimationLeashParent())//设置leash动画图层的父类为当前窗口的父类
.setName(surface + " - animation-leash of " + animationTypeToString(type))
// TODO(b/151665759) Defer reparent calls
// We want the leash to be visible immediately because the transaction which shows
// the leash may be deferred but the reparent will not. This will cause the leashed
// surface to be invisible until the deferred transaction is applied. If this
// doesn't work, you will can see the 2/3 button nav bar flicker during seamless
// rotation.
.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);//指定窗口的父类为leash动画图层
return leash;
}
}
以上代码需要重点关注以下几点
- 在WindowStateAnimator的loadAnimationAttr方法中,会判断使用哪种窗口动画以及进行窗口动画资源的加载。
- 在WindowState的startAnimation方法中,会创建LocalAnimationAdapter本地动画实例对象。
- 在SurfaceAnimator的createAnimationLeash方法中,会创建leash动画图层,并将该图层的父类设置为当前窗口的父类,将当前窗口的父类设置为leash动画图层。
2.1.3 时序图
三 窗口动画执行和移除Leash图层
窗口动画的执行流程和移除Leash图层的流程基本和Android 16系统源码_窗口动画(二)窗口显示动画源码调用流程这篇文章介绍的一样,这里不再展开。
四 移除窗口图层
4.1 remove方法调用流程
4.1.1堆栈信息
这里我们直接看RootWindowContainer的performSurfacePlacement方法。
class RootWindowContainer extends WindowContainer<DisplayContent>
implements DisplayManager.DisplayListener {
void performSurfacePlacementNoTrace() {
...代码省略...
//遍历WindowManagerService服务类型为ArrayList<WindowState>的mDestroySurface集合
i = mWmService.mDestroySurface.size();
if (i > 0) {
do {
i--;
WindowState win = mWmService.mDestroySurface.get(i);
win.mDestroying = false;
final DisplayContent displayContent = win.getDisplayContent();
if (displayContent.mInputMethodWindow == win) {
displayContent.setInputMethodWindowLocked(null);
}
if (displayContent.mWallpaperController.isWallpaperTarget(win)) {
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
}
//依次调用集合中WindowState元素的destroySurfaceUnchecked方法
win.destroySurfaceUnchecked();
} while (i > 0);
mWmService.mDestroySurface.clear();
}
...代码省略...
}
}
发现系统会遍历WindowManagerService的mDestroySurface集合中的元素,然后依次调用destroySurfaceUnchecked方法销毁图层。而经过搜索可以发现系统是在WindowState的onExitAnimationDone方法中往WindowManagerService的mDestroySurface集合中添加元素的。
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState,
InsetsControlTarget, InputTarget {
void onExitAnimationDone() {
...代码省略...
if (hasSurface) {
mWmService.mDestroySurface.add(this);
}
...代码省略...
}
}
4.1.2 源码调用流程
结合前面的堆栈信息可以梳理出一下源码调用流程。
//frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
class SurfaceAnimationRunner {
private static final class RunningAnimation {
final AnimationSpec mAnimSpec;
final SurfaceControl mLeash;
final Runnable mFinishCallback;
ValueAnimator mAnim;
@GuardedBy("mCancelLock")
private boolean mCancelled;
RunningAnimation(AnimationSpec animSpec, SurfaceControl leash, Runnable finishCallback) {
mAnimSpec = animSpec;
mLeash = leash;
mFinishCallback = finishCallback;
}
}
@GuardedBy("mLock")
private void startAnimationLocked(RunningAnimation a) {
...代码省略...;
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
...代码省略...
}
@Override
public void onAnimationEnd(Animator animation) {
synchronized (mLock) {
mRunningAnimations.remove(a.mLeash);
synchronized (mCancelLock) {
if (!a.mCancelled) {
// Post on other thread that we can push final state without jank.
//动画结束,触发leash图层对应的Runnable对象的run方法,
//触发在LocalAnimationAdapter中设置的回调,OnAnimationFinishedCallback的onAnimationFinished方法
mAnimationThreadHandler.post(a.mFinishCallback);
}
}
}
}
});
...代码省略...
}
}
//frameworks/base/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
class LocalAnimationAdapter implements AnimationAdapter {
private final AnimationSpec mSpec;
private final SurfaceAnimationRunner mAnimator;
LocalAnimationAdapter(AnimationSpec spec, SurfaceAnimationRunner animator) {
mSpec = spec;
mAnimator = animator;
}
@Override
public void startAnimation(SurfaceControl animationLeash, Transaction t,
@AnimationType int type, @NonNull OnAnimationFinishedCallback finishCallback) {
//窗口动画执行完毕会回调这里OnAnimationFinishedCallback的onAnimationFinished方法
mAnimator.startAnimation(mSpec, animationLeash, t,
() -> finishCallback.onAnimationFinished(type, this));
}
}
//frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimator.java
class SurfaceAnimator {
final OnAnimationFinishedCallback mInnerAnimationFinishedCallback;
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;
...代码省略...
//LocalAnimationAdapter的startAnimation方法最早是在这里传入的
mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback);
}
SurfaceAnimator(Animatable animatable,
@Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback,
WindowManagerService service) {
//mInnerAnimationFinishedCallback是在构造方法中被赋值的
mInnerAnimationFinishedCallback = getFinishedCallback(staticAnimationFinishedCallback);
}
//动画结束会触发这里的回调
private OnAnimationFinishedCallback getFinishedCallback(
@Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback) {
return (type, anim) -> {
synchronized (mService.mGlobalLock) {
...代码省略...
reset(mAnimatable.getPendingTransaction(), true /* destroyLeash */);
if (staticAnimationFinishedCallback != null) {
//回调OnAnimationFinishedCallback的onAnimationFinished方法,会触发WindowState的onAnimationFinished方法
staticAnimationFinishedCallback.onAnimationFinished(type, anim);
}
...代码省略...
}
};
}
}
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState,
InsetsControlTarget, InputTarget {
final WindowStateAnimator mWinAnimator;
@Override
protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
super.onAnimationFinished(type, anim);
mWinAnimator.onAnimationFinished();
}
}
class WindowStateAnimator {
final WindowState mWin;
void onAnimationFinished() {
...代码省略...
mWin.onExitAnimationDone();
...代码省略...
}
}
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState,
InsetsControlTarget, InputTarget {
void onExitAnimationDone() {
...代码省略...
if (hasSurface) {
//将当前窗口图层添加到WMS的mDestroySurface集合中
mWmService.mDestroySurface.add(this);
}
...代码省略...
}
}
class RootWindowContainer extends WindowContainer<DisplayContent>
implements DisplayManager.DisplayListener {
void performSurfacePlacement() {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement");
try {
performSurfacePlacementNoTrace();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
void performSurfacePlacementNoTrace() {
...代码省略...
//遍历WindowManagerService服务类型为ArrayList<WindowState>的mDestroySurface集合
i = mWmService.mDestroySurface.size();
if (i > 0) {
do {
i--;
WindowState win = mWmService.mDestroySurface.get(i);
win.mDestroying = false;
final DisplayContent displayContent = win.getDisplayContent();
if (displayContent.mInputMethodWindow == win) {
displayContent.setInputMethodWindowLocked(null);
}
if (displayContent.mWallpaperController.isWallpaperTarget(win)) {
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
}
//依次调用集合中WindowState元素的destroySurfaceUnchecked方法
win.destroySurfaceUnchecked();
} while (i > 0);
mWmService.mDestroySurface.clear();
}
...代码省略...
}
}
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState,
InsetsControlTarget, InputTarget {
void destroySurfaceUnchecked() {
mWinAnimator.destroySurfaceLocked(mTmpTransaction);
...代码省略...
}
}
class WindowStateAnimator {
void destroySurfaceLocked(SurfaceControl.Transaction t) {
...代码省略...
destroySurface(t);
...代码省略...
}
WindowSurfaceController mSurfaceController;
void destroySurface(SurfaceControl.Transaction t) {
...代码省略...
if (mSurfaceController != null) {
mSurfaceController.destroy(t);
}
...代码省略...
}
}
class WindowSurfaceController {
void destroy(SurfaceControl.Transaction t) {
ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
"Destroying surface %s called by %s", this, Debug.getCallers(8));
try {
if (mSurfaceControl != null) {
//调用SurfaceControl$Transaction的remove方法
t.remove(mSurfaceControl);
}
} catch (RuntimeException e) {
Slog.w(TAG, "Error destroying surface in: " + this, e);
} finally {
setShown(false);
mSurfaceControl = null;
}
}
}
public final class SurfaceControl implements Parcelable {
public static class Transaction implements Closeable, Parcelable {
public Transaction remove(@NonNull SurfaceControl sc) {
if(sc.toString().contains("- animation-leash of window_animation")){
Log.i(TAG, "LPSurface.remove: sc = "+sc, new Exception());
}
//将图层的父节点设置为空
reparent(sc, null);
//对图层进行释放
sc.release();
return this;
}
}
}
4.1.3 时序图
将窗口图层添加到WindowManagerService待销毁图层集合中。
系统遍历WindowManagerService中待销毁图层集合,依次进行图层移除。