背景:
在学员群中有学员朋友在分析systemserver的systrace和perfetto时候,提出了关于android.anim和android.anim.lf两个线程的相关疑问,主要是android.anim和android.anim.lf两个线程分别用于什么,有啥区别。针对这个疑问其实比较多学员朋友同样也想要知道答案,这里干脆写个文章来解答,分别日后学员朋友好查询,不需要挨个回答。
源码注释解答
首先看一下关于这里两个线程源码寻找方式:
test@test:~/aosp/frameworks/base$ grep "\"android.anim" ./ -rn | grep java
./tools/preload-check/src/com/android/preload/check/PreloadCheck.java:68: run("com.android.preload.check.Initialized", "android.animation.Animator");
./services/core/java/com/android/server/AnimationThread.java:35: super("android.anim", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
./services/core/java/com/android/server/wm/SurfaceAnimationThread.java:35: super("android.anim.lf", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
可以看到./services/core/java/com/android/server/AnimationThread.java这个类就是代表的"android.anim"线程
./services/core/java/com/android/server/wm/SurfaceAnimationThread.java代表就是"android.anim.lf"线程
看看对应类的注释:
AnimationThread类
/**
* Thread for handling all legacy window animations, or anything that's directly impacting
* animations like starting windows or traversals.
*/
public final class AnimationThread extends ServiceThread {
private static AnimationThread sInstance;
private static Handler sHandler;
private AnimationThread() {
super("android.anim", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
}
注释说明:
AnimationThread主要用于处理一些遗留的窗口动画,货值其他直接会影响动画的,比如启动窗口,或者遍历树等
SurfaceAnimationThread类
/**
* Thread for running {@link SurfaceAnimationRunner} that does not hold the window manager lock.
*/
public final class SurfaceAnimationThread extends ServiceThread {
private static SurfaceAnimationThread sInstance;
private static Handler sHandler;
private SurfaceAnimationThread() {
super("android.anim.lf", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
}
注释说明:
这个其实就是新版本窗口动画流畅更新主要线程,也课程也讲解过的引入leash这种图层进行动画,不需要在持有 window manager lock的那一把大锁,可以直接对SurfaceControl的图层进行动画操作。所以更加流畅的核心就是不用再持有windowmanagerservice的大锁,所以独立出来了单独的动画线程来执行,减轻android.anim的负担
总结:
其实上面的注释也讲的比较清楚了,核心就是为了动画更加流畅,改进成了动画不需要在单独依赖windowmanagerservice的大锁,所以独立出来了一个单独的动画独立线程android.anim.lf。
这里可能学员朋友又有疑问,窗口动画都被搞到了线程android.anim.lf,那原来的线程android.anim岂不是架空了?android.anim还干些啥?
这个疑问同样AnimationThread的注释也已经说明了,主要干一些遗留窗口动画,还有启动窗口,遍历窗口等工作,具体也可以看一下相关的perfetto
android.anim的perfetto/systrace
trace可以看出android.anim会执行Traverser相关的任务
代码可以看这里
void requestTraversal() {
if (mTraversalScheduled) {
return;
}
// Set as scheduled even the request will be deferred because mDeferredRequests is also
// increased, then the end of deferring will perform the request.
mTraversalScheduled = true;
if (mDeferDepth > 0) {
mDeferredRequests++;
if (DEBUG) Slog.i(TAG, "Defer requestTraversal " + Debug.getCallers(3));
return;
}
mService.mAnimationHandler.post(mPerformSurfacePlacement);
}
当然也有很多地方会触发相关的animate,但是这个animate相关的活,和“动画”关系已经不那么大
可以看到这里的scheduleAnimation注释:
/**
* Trigger a call to prepareSurfaces from the animation thread, such that pending transactions
* will be applied.
*/
void scheduleAnimation() {
if (mParent != null) {
mParent.scheduleAnimation();
}
}
这里主要是来触发prepareSrufaces这个方法,让一些pending的事物进行apply
相关的animate方法如下:
private void animate(long frameTimeNs, long vsyncId) {
scheduleAnimation();
final RootWindowContainer root = mService.mRoot;
mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
mBulkUpdateParams = 0;
root.mOrientationChangeComplete = true;
if (DEBUG_WINDOW_TRACE) {
Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
}
ProtoLog.i(WM_SHOW_TRANSACTIONS, ">>> OPEN TRANSACTION animate");
mService.openSurfaceTransaction();
try {
// Remove all deferred displays, tasks, and activities.
root.handleCompleteDeferredRemoval();
final AccessibilityController accessibilityController =
mService.mAccessibilityController;
final int numDisplays = mDisplayContentsAnimators.size();
for (int i = 0; i < numDisplays; i++) {
final int displayId = mDisplayContentsAnimators.keyAt(i);
final DisplayContent dc = root.getDisplayContent(displayId);
// Update animations of all applications, including those associated with
// exiting/removed apps.
dc.updateWindowsForAnimator();
dc.prepareSurfaces();
}
for (int i = 0; i < numDisplays; i++) {
final int displayId = mDisplayContentsAnimators.keyAt(i);
final DisplayContent dc = root.getDisplayContent(displayId);
dc.checkAppWindowsReadyToShow();
if (accessibilityController.hasCallbacks()) {
accessibilityController.drawMagnifiedRegionBorderIfNeeded(displayId,
mTransaction);
}
}
cancelAnimation();
if (mService.mWatermark != null) {
mService.mWatermark.drawIfNeeded();
}
} catch (RuntimeException e) {
Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
}
final boolean hasPendingLayoutChanges = root.hasPendingLayoutChanges(this);
final boolean doRequest = (mBulkUpdateParams != 0 || root.mOrientationChangeComplete)
&& root.copyAnimToLayoutParams();
if (hasPendingLayoutChanges || doRequest) {
mService.mWindowPlacerLocked.requestTraversal();
}
final boolean rootAnimating = root.isAnimating(TRANSITION | CHILDREN /* flags */,
ANIMATION_TYPE_ALL /* typesToCheck */);
if (rootAnimating && !mLastRootAnimating) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
}
if (!rootAnimating && mLastRootAnimating) {
mService.mWindowPlacerLocked.requestTraversal();
Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
}
mLastRootAnimating = rootAnimating;
final boolean runningExpensiveAnimations =
root.isAnimating(TRANSITION | CHILDREN /* flags */,
ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_SCREEN_ROTATION
| ANIMATION_TYPE_RECENTS /* typesToCheck */);
if (runningExpensiveAnimations && !mRunningExpensiveAnimations) {
// Usually app transitions put quite a load onto the system already (with all the things
// happening in app), so pause task snapshot persisting to not increase the load.
mService.mTaskSnapshotController.setPersisterPaused(true);
mTransaction.setEarlyWakeupStart();
} else if (!runningExpensiveAnimations && mRunningExpensiveAnimations) {
mService.mTaskSnapshotController.setPersisterPaused(false);
mTransaction.setEarlyWakeupEnd();
}
mRunningExpensiveAnimations = runningExpensiveAnimations;
SurfaceControl.mergeToGlobalTransaction(mTransaction);
mService.closeSurfaceTransaction("WindowAnimator");
ProtoLog.i(WM_SHOW_TRANSACTIONS, "<<< CLOSE TRANSACTION animate");
if (mRemoveReplacedWindows) {
root.removeReplacedWindows();
mRemoveReplacedWindows = false;
}
mService.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
executeAfterPrepareSurfacesRunnables();
}
相关的trace:
本文章更多详细代码和资料需要购买课程获取
hal+perfetto+surfaceflinger
https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg
私聊作者+v(androidframework007)
其他课程七件套专题:
点击这里
https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw