Android-Choreographer工作原理,2021大厂Android面试经验
作者:互联网
// mTraversalRunnable 是一个 Runnable 实例
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
// 移除同步屏障
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
// 真正执行View的measure,layout,draw流程
performTraversals();
}
}
首先使用 mTraversalScheduled 字段保证同时间多次更改只会刷新一次,然后为当前线程的 MessageQueue 添加同步屏障来屏蔽同步消息,保证 VSync 信号到来后立即执行绘制,而不是要等前面的同步消息。调用 mChoreographer.postCallback() 方法发送了一个会在下一帧执行的回调,即在下一个 VSync 信号到来时会执行TraversalRunnable–>doTraversal()–>performTraversals()–>绘制流程。同步屏障可以参考 Android消息机制。
Choreographer实例化
首先看一下 Choreographer 的实例化过程,它在 ViewRootImpl 构造方法中实例化,ViewRootImpl 的实例化时机可以参考 Android-Window机制原理。
// ViewRootImpl在WindowManager.addView时创建 public ViewRootImpl(Context context, Display display) { // ... mChoreographer = Choreographer.getInstance(); // ... } public final class Choreographer { private static volatile Choreographer mMainInstance; private static final ThreadLocal sThreadInstance = new ThreadLocal() { @Override protected Choreographer initialValue() { Looper looper = Looper.myLooper(); // VSYNC_SOURCE_APP = 0; -- APP // VSYNC_SOURCE_SURFACE_FLINGER = 1; -- SurfaceFlinger Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP); // ... return choreographer; } }; public static Choreographer getInstance() { return sThreadInstance.get(); } } 可知 Choreographer 和 Looper 一样都是线程单例的,由 ThreadLocal 实现,参考ThreadLocal原理。
public final class Choreographer { // 4.1以上默认是true // Enable/disable vsync for animations and drawing. private static final boolean USE_VSYNC = SystemProperties.getBoolean("debug.choreographer.vsync", true); // VSync事件接收器 private final FrameDisplayEventReceiver mDisplayEventReceiver; private Choreographer(Looper looper, int vsyncSource) { mLooper = looper; mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper, vsyncSource) : null; // ... } } 在 Choreographer 实例化时创建了一个 FrameDisplayEventReceiver 对象,它用来注册 Vsync 信号。 # Vsync信号注册 # DisplayEventReceiver mDisplayEventReceiver 是 FrameDisplayEventReceiver 类型的实例,在Choreographer构造方法中实例化,其父类为 DisplayEventReceiver。
public abstract class DisplayEventReceiver { public static final int VSYNC_SOURCE_APP = 0; private long mReceiverPtr; public DisplayEventReceiver(Looper looper, int vsyncSource) { mMessageQueue = looper.getQueue(); // 注册VSYNC信号监听者 mReceiverPtr = nativeInit(new WeakReference(this), mMessageQueue, vsyncSource); } private static native long nativeInit(WeakReference receiver, MessageQueue messageQueue, int vsyncSource); } # nativeInit nativeInit是一个native方法,其实现在frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp中:static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj, jint vsyncSource) { sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); sp receiver = new NativeDisplayEventReceiver(env, receiverWeak, messageQueue, vsyncSource); status_t status = receiver->initialize(); receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object return reinterpret_cast(receiver.get()); } NativeDisplayEventReceiver 继承自 DisplayEventDispatcher:DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) { sp sf(ComposerService::getComposerService()); if (sf != NULL) { mEventConnection = sf->createDisplayEventConnection(vsyncSource); if (mEventConnection != NULL) { mDataChannel = std::make_unique(); mEventConnection->stealReceiveChannel(mDataChannel.get()); } } } sp SurfaceFlinger::createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource) { if (vsyncSource == eVsyncSourceSurfaceFlinger) { return mSFEventThread->createEventConnection(); } else { // vsyncSource 是 APP return mEventThread->createEventConnection(); } } 从 SurfaceFlinger 启动与工作流程 可以知道 EventThread.createEventConnection 创建了一个对 Vsync 信号感兴趣的连接,具体逻辑可以阅读这篇文章。initialize 方法如下:// frameworks/base/libs/androidfw/DisplayEventDispatcher.cpp status_t DisplayEventDispatcher::initialize() { // DisplayEventReceiver mReceiver; status_t result = mReceiver.initCheck(); int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL); if (rc < 0) { return UNKNOWN_ERROR; } return OK; } mReceiver 是 DisplayEventReceiver 类型实例,位于frameworks/native/libs/gui/DisplayEventReceiver.cpp。mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL) 用来监听 mReceiver 所获取的文件句柄,当**有存在对 Vsync 信号感兴趣的连接**且**接收到了 Vsync 信号**时,会发送数据到 mReceiver, 然后回调到 DisplayEventDispatcher 中的 handleEvent 方法,具体源码参考 SurfaceFlinger 启动与工作流程 中 addFd 的解析。 # 请求Vsync信号 上面已经注册了一个对 Vsync 信号感兴趣的连接,在 Vsync 信号到来后,会回调到 DisplayEventDispatcher.handleEvent 方法。于是接下来我们需要请求 Vsync 信号。看一下上面调用的代码:mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null),它的调用链是: Choreographer.postCallback -> Choreographer.postCallbackDelayedInternal -> Choreographer.scheduleFrameLocked -> Choreographer.scheduleVsyncLocked 方法,节省篇幅,具体代码不贴出了:private void postCallbackDelayedInternal(int callbackType, Object action, Object token, long delayMillis) { synchronized (mLock) { final long now = SystemClock.uptimeMillis(); final long dueTime = now + delayMillis; // 对应类型的 CallbackQueue 添加 Callback mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token); // ... } } private void scheduleVsyncLocked() { mDisplayEventReceiver.scheduleVsync(); } // DisplayEventReceiver public void scheduleVsync() { if (mReceiverPtr == 0) { // ... } else { nativeScheduleVsync(mReceiverPtr); } } 接着就到了 native 层代码:// frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) { sp receiver = reinterpret_cast
标签:Choreographer,vsyncSource,private,2021,Vsync,DisplayEventReceiver,Android,public 来源: https://blog.csdn.net/m0_65145219/article/details/122190369