本文基于 aosp android-14.0.0_r15 版本讲解。
# Choreographer 的作用
Choreographer 主要用于负责软件 Vsync 信号的请求与接受。
- App 需要绘制一帧时,Choreographer 负责向 SurfaceFlinger 请求新的软件 Vsync 信号
- 软件 Vsync 信号到达时,Choreographer 负责新的输入、动画、和绘制等任务的执行。
# 1. Choreographer 的使用
当界面需要刷新时,会调用到 View#invalidate()
或 View#requestLayout()
方法,两者都会调用到 ViewRootImpl#scheduleTraversals()
方法。
// /frameworks/base/core/java/android/view/ViewRootImpl.java
public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,
WindowLayout windowLayout) {
//......
// 关注点1,Choreographer 的初始化
mChoreographer = Choreographer.getInstance();
//......
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 关注点2,Choreographer post 任务
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 2. Choreographer 的初始化
// /home/zzh0838/Project/aosp/android-14.0.0_r15/frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
// ......
private static volatile Choreographer mMainInstance;
// .....
private static final ThreadLocal<Choreographer> sThreadInstance =
new ThreadLocal<Choreographer>() {
@Override
protected Choreographer initialValue() {
Looper looper = Looper.myLooper();
if (looper == null) {
throw new IllegalStateException("The current thread must have a looper!");
}
Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
if (looper == Looper.getMainLooper()) {
mMainInstance = choreographer;
}
return choreographer;
}
};
// ......
public static Choreographer getInstance() {
return sThreadInstance.get();
}
// ......
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
可以看出 Choreographer 是线程单例的。
接着看他的构造函数
private final Looper mLooper;
private final FrameHandler mHandler;
private final FrameDisplayEventReceiver mDisplayEventReceiver;
private final CallbackQueue[] mCallbackQueues;
private Choreographer(Looper looper, int vsyncSource) {
this(looper, vsyncSource, /* layerHandle */ 0L);
}
private Choreographer(Looper looper, int vsyncSource, long layerHandle) {
// Choreographer 的所有任务都会通过 Looper 执行
mLooper = looper;
mHandler = new FrameHandler(looper);
// 关注点,FrameDisplayEventReceiver 对象用于请求并接收软件 VSync 信号
mDisplayEventReceiver = USE_VSYNC
? new FrameDisplayEventReceiver(looper, vsyncSource, layerHandle)
: null;
// 上一个 frame 渲染的时间点
mLastFrameTimeNanos = Long.MIN_VALUE;
// 染一帧的时间约等于 16666.66ns ≈ 16.6ms (60hz 为例)
mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
// 关注点,回调队列,非常重要
// CallbackQueue 数组,默认数组大小为 5
// CallbackQueue 数组中保存了输入(CALLBACK_INPUT)、动画(CALLBACK_ANIMATION)、绘制(CALLBACK_TRAVERSAL)等类型的回调,将在下一帧开始渲染时回调
mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
for (int i = 0; i <= CALLBACK_LAST; i++) {
mCallbackQueues[i] = new CallbackQueue();
}
// b/68769804: For low FPS experiments.
setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 2.1 FrameHandler 的实现
// frameworks/base/core/java/android/view/Choreographer.java
private final class FrameHandler extends Handler {
public FrameHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_DO_FRAME:
// 当 VSync 信号到来时执行 doFrame 开始渲染下一帧
doFrame(System.nanoTime(), 0, new DisplayEventReceiver.VsyncEventData());
break;
case MSG_DO_SCHEDULE_VSYNC:
// 请求 VSync 信号
doScheduleVsync();
break;
case MSG_DO_SCHEDULE_CALLBACK:
// 请求执行延迟任务回调
doScheduleCallback(msg.arg1);
break;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 2.2 FrameDisplayEventReceiver 的实现
// frameworks/base/core/java/android/view/Choreographer.java
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
private final VsyncEventData mLastVsyncEventData = new VsyncEventData();
FrameDisplayEventReceiver(Looper looper, int vsyncSource, long layerHandle) {
super(looper, vsyncSource, /* eventRegistration */ 0, layerHandle);
}
// TODO(b/116025192): physicalDisplayId is ignored because SF only emits VSYNC events for
// the internal display and DisplayEventReceiver#scheduleVsync only allows requesting VSYNC
// for the internal display implicitly.
// 收到软件 Vsync 时,会调用到该方法
@Override
public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
VsyncEventData vsyncEventData) {
try {
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW,
"Choreographer#onVsync "
+ vsyncEventData.preferredFrameTimeline().vsyncId);
}
// Post the vsync event to the Handler.
// The idea is to prevent incoming vsync events from completely starving
// the message queue. If there are no messages in the queue with timestamps
// earlier than the frame time, then the vsync event will be processed immediately.
// Otherwise, messages that predate the vsync event will be handled first.
long now = System.nanoTime();
if (timestampNanos > now) {
Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
+ " ms in the future! Check that graphics HAL is generating vsync "
+ "timestamps using the correct timebase.");
timestampNanos = now;
}
if (mHavePendingVsync) {
Log.w(TAG, "Already have a pending vsync event. There should only be "
+ "one at a time.");
} else {
mHavePendingVsync = true;
}
mTimestampNanos = timestampNanos;
mFrame = frame;
mLastVsyncEventData.copyFrom(vsyncEventData);
Message msg = Message.obtain(mHandler, this); // 回调方法是 this
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
@Override
public void run() { // 具体回调
mHavePendingVsync = false;
// 绘制下一帧
doFrame(mTimestampNanos, mFrame, mLastVsyncEventData);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
FrameDisplayEventReceiver 的父类 DisplayEventReceiver 的实现如下:
// /frameworks/base/core/java/android/view/DisplayEventReceiver.java
public abstract class DisplayEventReceiver {
// ......
private long mReceiverPtr;
private MessageQueue mMessageQueue;
private final VsyncEventData mVsyncEventData = new VsyncEventData();
// ?
private Runnable mFreeNativeResources;
// ......
private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver,
WeakReference<VsyncEventData> vsyncEventData,
MessageQueue messageQueue, int vsyncSource, int eventRegistration, long layerHandle);
private static native long nativeGetDisplayEventReceiverFinalizer();
@FastNative
private static native void nativeScheduleVsync(long receiverPtr);
private static native VsyncEventData nativeGetLatestVsyncEventData(long receiverPtr);
// .......
public DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration,
long layerHandle) {
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mMessageQueue = looper.getQueue();
// 关注点
mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this),
new WeakReference<VsyncEventData>(mVsyncEventData),
mMessageQueue,
vsyncSource, eventRegistration, layerHandle);
mFreeNativeResources = sNativeAllocationRegistry.registerNativeAllocation(this,
mReceiverPtr);
}
public void scheduleVsync() {
if (mReceiverPtr == 0) {
Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
+ "receiver has already been disposed.");
} else {
nativeScheduleVsync(mReceiverPtr);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
接着看 Native 层:
// /frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject vsyncEventDataWeak,
jobject messageQueueObj, jint vsyncSource, jint eventRegistration,
jlong layerHandle) {
// 由 Java 层传入的 MessageQueue 获取 native 层对应的 MessageQueue
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
// 构造 NativeDisplayEventReceiver 对象
sp<NativeDisplayEventReceiver> receiver =
new NativeDisplayEventReceiver(env, receiverWeak, vsyncEventDataWeak, messageQueue,
vsyncSource, eventRegistration, layerHandle);
// 关注点
status_t status = receiver->initialize();
if (status) {
String8 message;
message.appendFormat("Failed to initialize display event receiver. status=%d", status);
jniThrowRuntimeException(env, message.string());
return 0;
}
receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
return reinterpret_cast<jlong>(receiver.get());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
- 构造 NativeDisplayEventReceiver 对象
- NativeDisplayEventReceiver:initialize()
NativeDisplayEventReceiver 的实现:
// /frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp
class NativeDisplayEventReceiver : public DisplayEventDispatcher {
public:
NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak, jobject vsyncEventDataWeak,
const sp<MessageQueue>& messageQueue, jint vsyncSource,
jint eventRegistration, jlong layerHandle);
void dispose();
protected:
virtual ~NativeDisplayEventReceiver();
private:
// Java 层的 DisplayEventReceiver
jobject mReceiverWeakGlobal;
jobject mVsyncEventDataWeakGlobal;
sp<MessageQueue> mMessageQueue;
// 分发 Vsync
void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
VsyncEventData vsyncEventData) override;
void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId,
nsecs_t renderPeriod) override;
void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
std::vector<FrameRateOverride> overrides) override;
void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) override {}
};
NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak,
jobject vsyncEventDataWeak,
const sp<MessageQueue>& messageQueue,
jint vsyncSource, jint eventRegistration,
jlong layerHandle)
: DisplayEventDispatcher(messageQueue->getLooper(),
static_cast<gui::ISurfaceComposer::VsyncSource>(vsyncSource),
static_cast<gui::ISurfaceComposer::EventRegistration>(
eventRegistration),
layerHandle != 0 ? sp<IBinder>::fromExisting(
reinterpret_cast<IBinder*>(layerHandle))
: nullptr),
mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
mVsyncEventDataWeakGlobal(env->NewGlobalRef(vsyncEventDataWeak)),
mMessageQueue(messageQueue) {
ALOGV("receiver %p ~ Initializing display event receiver.", this);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// /frameworks/native/libs/gui/include/gui/DisplayEventDispatcher.h
class DisplayEventDispatcher : public LooperCallback {
public:
explicit DisplayEventDispatcher(const sp<Looper>& looper,
gui::ISurfaceComposer::VsyncSource vsyncSource =
gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp,
EventRegistrationFlags eventRegistration = {},
const sp<IBinder>& layerHandle = nullptr);
status_t initialize();
void dispose();
status_t scheduleVsync();
void injectEvent(const DisplayEventReceiver::Event& event);
int getFd() const;
virtual int handleEvent(int receiveFd, int events, void* data);
status_t getLatestVsyncEventData(ParcelableVsyncEventData* outVsyncEventData) const;
protected:
virtual ~DisplayEventDispatcher() = default;
private:
sp<Looper> mLooper;
DisplayEventReceiver mReceiver;
bool mWaitingForVsync;
uint32_t mLastVsyncCount;
nsecs_t mLastScheduleVsyncTime;
std::vector<FrameRateOverride> mFrameRateOverrides;
virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
VsyncEventData vsyncEventData) = 0;
virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
bool connected) = 0;
virtual void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId,
nsecs_t vsyncPeriod) = 0;
// AChoreographer-specific hook for processing null-events so that looper
// can be properly poked.
virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0;
virtual void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
std::vector<FrameRateOverride> overrides) = 0;
bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
uint32_t* outCount, VsyncEventData* outVsyncEventData);
void populateFrameTimelines(const DisplayEventReceiver::Event& event,
VsyncEventData* outVsyncEventData) const;
};
// /frameworks/native/libs/gui/DisplayEventDispatcher.cpp
DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
gui::ISurfaceComposer::VsyncSource vsyncSource,
EventRegistrationFlags eventRegistration,
const sp<IBinder>& layerHandle)
: mLooper(looper),
mReceiver(vsyncSource, eventRegistration, layerHandle),
mWaitingForVsync(false),
mLastVsyncCount(0),
mLastScheduleVsyncTime(0) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
DisplayEventReceiver 的初始化:
// /frameworks/native/libs/gui/include/gui/DisplayEventReceiver.h
class DisplayEventReceiver {
// ......
private:
sp<IDisplayEventConnection> mEventConnection;
std::unique_ptr<gui::BitTube> mDataChannel;
}
// /frameworks/native/libs/gui/DisplayEventReceiver.cpp
DisplayEventReceiver::DisplayEventReceiver(gui::ISurfaceComposer::VsyncSource vsyncSource,
EventRegistrationFlags eventRegistration,
const sp<IBinder>& layerHandle) {
// 获取 Binder 服务代理端
sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
if (sf != nullptr) {
// 获取匿名 Binder 服务代理端 mEventConnection
mEventConnection = nullptr;
binder::Status status =
sf->createDisplayEventConnection(vsyncSource,
static_cast<
gui::ISurfaceComposer::EventRegistration>(
eventRegistration.get()),
layerHandle, &mEventConnection);
if (status.isOk() && mEventConnection != nullptr) {
mDataChannel = std::make_unique<gui::BitTube>();
// 拿到接受 Vsync 信号的 fd
status = mEventConnection->stealReceiveChannel(mDataChannel.get());
if (!status.isOk()) {
ALOGE("stealReceiveChannel failed: %s", status.toString8().c_str());
mInitError = std::make_optional<status_t>(status.transactionError());
mDataChannel.reset();
mEventConnection.clear();
}
} else {
ALOGE("DisplayEventConnection creation failed: status=%s", status.toString8().c_str());
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
接着看 NativeDisplayEventReceiver:initialize()
// /frameworks/native/libs/gui/DisplayEventDispatcher.cpp
status_t DisplayEventDispatcher::initialize() {
status_t result = mReceiver.initCheck();
if (result) {
ALOGW("Failed to initialize display event receiver, status=%d", result);
return result;
}
if (mLooper != nullptr) {
// 监听 fd 回调事件,回调对象是 this,即 DisplayEventDispatcher
int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
if (rc < 0) {
return UNKNOWN_ERROR;
}
}
return OK;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 2.3 CallbackQueue
Choreographer 中定义了 5 种类型的 Callback:
// frameworks/base/core/java/android/view/Choreographer.java
// 输入事件,首先执行
public static final int CALLBACK_INPUT = 0;
// 动画事件,在 CALLBACK_INSETS_ANIMATION 之前执行
public static final int CALLBACK_ANIMATION = 1;
// 插入更新动画事件,INPUT 和 ANIMATION 后面执行,TRAVERSAL 之前执行
public static final int CALLBACK_INSETS_ANIMATION = 2;
// 处理布局和绘制事件,在处理完上述异步消息之后运行
public static final int CALLBACK_TRAVERSAL = 3;
// 提交,和提交任务有关(在 API Level 23 添加),最后执⾏,遍历完成的提交操作,⽤来修正动画启动时间
public static final int CALLBACK_COMMIT = 4;
// 数组默认长度 5, 上面的一个常量作为 index 对应数组的一个成员
private final CallbackQueue[] mCallbackQueues;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// frameworks/base/core/java/android/view/Choreographer.java
private final class CallbackQueue {
// 内部是一个链表
private CallbackRecord mHead;
// ......
}
private static final class CallbackRecord {
public CallbackRecord next;
public long dueTime;
/** Runnable or FrameCallback or VsyncCallback object. */
public Object action;
/** Denotes the action type. */
public Object token;
// .......
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 3. Choreographer 添加任务过程分析 / Vsync 申请阶段
// /frameworks/base/core/java/android/view/Choreographer.java
public void postCallback(int callbackType, Runnable action, Object token) {
postCallbackDelayed(callbackType, action, token, 0);
}
public void postCallbackDelayed(int callbackType,
Runnable action, Object token, long delayMillis) {
if (action == null) {
throw new IllegalArgumentException("action must not be null");
}
if (callbackType < 0 || callbackType > CALLBACK_LAST) {
throw new IllegalArgumentException("callbackType is invalid");
}
postCallbackDelayedInternal(callbackType, action, token, delayMillis);
}
private void postCallbackDelayedInternal(int callbackType,
Object action, Object token, long delayMillis) {
if (DEBUG_FRAMES) {
Log.d(TAG, "PostCallback: type=" + callbackType
+ ", action=" + action + ", token=" + token
+ ", delayMillis=" + delayMillis);
}
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
if (dueTime <= now) {
// 立即执行、请求 VSync 信号
scheduleFrameLocked(now);
} else {
// 延迟到指定时间运行,最终仍然会调用 scheduleFrameLocked
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// /frameworks/base/core/java/android/view/Choreographer.java
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame on vsync.");
}
// If running on the Looper thread, then schedule the vsync immediately,
// otherwise post a message to schedule the vsync from the UI thread
// as soon as possible.
// 判断当前执行的线程,是否是 mLooper 所在工作线程(即 UI 主线程)
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();
} else { // 如果不是 mLooper 所在工作线程(即 UI 主线程),发送消息到 FrameHandler 异步消息处理
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
final long nextFrameTime = Math.max(
mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
}
Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextFrameTime);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// /frameworks/base/core/java/android/view/Choreographer.java
private void scheduleVsyncLocked() {
try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#scheduleVsyncLocked");
mDisplayEventReceiver.scheduleVsync();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
// /frameworks/base/core/java/android/view/DisplayEventReceiver.java
public void scheduleVsync() {
if (mReceiverPtr == 0) {
Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
+ "receiver has already been disposed.");
} else {
nativeScheduleVsync(mReceiverPtr);
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
// /frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp
static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
sp<NativeDisplayEventReceiver> receiver =
reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
status_t status = receiver->scheduleVsync();
if (status) {
String8 message;
message.appendFormat("Failed to schedule next vertical sync pulse. status=%d", status);
jniThrowRuntimeException(env, message.string());
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
// /frameworks/native/libs/gui/DisplayEventDispatcher.cpp
status_t DisplayEventDispatcher::scheduleVsync() {
if (!mWaitingForVsync) {
ALOGV("dispatcher %p ~ Scheduling vsync.", this);
// Drain all pending events.
nsecs_t vsyncTimestamp;
PhysicalDisplayId vsyncDisplayId;
uint32_t vsyncCount;
VsyncEventData vsyncEventData;
// 处理挂起事件
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this,
ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
}
// DisplayEventReceiver 请求下一个 VSync 信号
status_t status = mReceiver.requestNextVsync();
if (status) {
ALOGW("Failed to request next vsync, status=%d", status);
return status;
}
mWaitingForVsync = true;
mLastScheduleVsyncTime = systemTime(SYSTEM_TIME_MONOTONIC);
}
return OK;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
处理挂起的 Vsync 信号:
// /frameworks/native/libs/gui/DisplayEventDispatcher.cpp
bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp,
PhysicalDisplayId* outDisplayId,
uint32_t* outCount,
VsyncEventData* outVsyncEventData) {
bool gotVsync = false;
DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
ssize_t n;
while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
ALOGV("dispatcher %p ~ Read %d events.", this, int(n));
mFrameRateOverrides.reserve(n);
for (ssize_t i = 0; i < n; i++) {
const DisplayEventReceiver::Event& ev = buf[i];
switch (ev.header.type) {
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
// Later vsync events will just overwrite the info from earlier
// ones. That's fine, we only care about the most recent.
gotVsync = true;
// 只会保存最新的那个 VSync 的 timestamp
*outTimestamp = ev.header.timestamp;
*outDisplayId = ev.header.displayId;
*outCount = ev.vsync.count;
*outVsyncEventData = ev.vsync.vsyncData;
break;
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);
break;
case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE:
dispatchModeChanged(ev.header.timestamp, ev.header.displayId,
ev.modeChange.modeId, ev.modeChange.vsyncPeriod);
break;
case DisplayEventReceiver::DISPLAY_EVENT_NULL:
dispatchNullEvent(ev.header.timestamp, ev.header.displayId);
break;
case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
mFrameRateOverrides.emplace_back(ev.frameRateOverride);
break;
case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
dispatchFrameRateOverrides(ev.header.timestamp, ev.header.displayId,
std::move(mFrameRateOverrides));
break;
default:
ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type);
break;
}
}
}
if (n < 0) {
ALOGW("Failed to get events from display event dispatcher, status=%d", status_t(n));
}
return gotVsync;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
mReceiver.getEvents:
// /frameworks/native/libs/gui/DisplayEventReceiver.cpp
ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
size_t count) {
return DisplayEventReceiver::getEvents(mDataChannel.get(), events, count);
}
ssize_t DisplayEventReceiver::getEvents(gui::BitTube* dataChannel,
Event* events, size_t count)
{
// socket fd 读数据
return gui::BitTube::recvObjects(dataChannel, events, count);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
// /frameworks/native/libs/gui/DisplayEventReceiver.cpp
status_t DisplayEventReceiver::requestNextVsync() {
if (mEventConnection != nullptr) {
// binder 远程调用
mEventConnection->requestNextVsync();
return NO_ERROR;
}
return mInitError.has_value() ? mInitError.value() : NO_INIT;
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 4. App 端 Vsync 信号分发过程
app 端,收到 Vsync 信号后,回调到
// /frameworks/native/libs/gui/DisplayEventDispatcher.cpp
int DisplayEventDispatcher::handleEvent(int, int events, void*) {
if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
ALOGE("Display event receiver pipe was closed or an error occurred. "
"events=0x%x",
events);
return 0; // remove the callback
}
if (!(events & Looper::EVENT_INPUT)) {
ALOGW("Received spurious callback for unhandled poll event. "
"events=0x%x",
events);
return 1; // keep the callback
}
// Drain all pending events, keep the last vsync.
nsecs_t vsyncTimestamp;
PhysicalDisplayId vsyncDisplayId;
uint32_t vsyncCount;
VsyncEventData vsyncEventData;
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64
", displayId=%s, count=%d, vsyncId=%" PRId64,
this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount,
vsyncEventData.preferredVsyncId());
mWaitingForVsync = false;
mLastVsyncCount = vsyncCount;
dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
}
if (mWaitingForVsync) {
const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
const nsecs_t vsyncScheduleDelay = currentTime - mLastScheduleVsyncTime;
if (vsyncScheduleDelay > WAITING_FOR_VSYNC_TIMEOUT) {
ALOGW("Vsync time out! vsyncScheduleDelay=%" PRId64 "ms", ns2ms(vsyncScheduleDelay));
mWaitingForVsync = false;
dispatchVsync(currentTime, vsyncDisplayId /* displayId is not used */,
++mLastVsyncCount, vsyncEventData /* empty data */);
}
}
return 1; // keep the callback
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// /frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,
uint32_t count, VsyncEventData vsyncEventData) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
ScopedLocalRef<jobject> vsyncEventDataObj(env, GetReferent(env, mVsyncEventDataWeakGlobal));
if (receiverObj.get() && vsyncEventDataObj.get()) {
ALOGV("receiver %p ~ Invoking vsync handler.", this);
env->SetIntField(vsyncEventDataObj.get(),
gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo
.preferredFrameTimelineIndex,
vsyncEventData.preferredFrameTimelineIndex);
env->SetIntField(vsyncEventDataObj.get(),
gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo
.frameTimelinesLength,
vsyncEventData.frameTimelinesLength);
env->SetLongField(vsyncEventDataObj.get(),
gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.frameInterval,
vsyncEventData.frameInterval);
ScopedLocalRef<jobjectArray>
frameTimelinesObj(env,
reinterpret_cast<jobjectArray>(
env->GetObjectField(vsyncEventDataObj.get(),
gDisplayEventReceiverClassInfo
.vsyncEventDataClassInfo
.frameTimelines)));
for (int i = 0; i < vsyncEventData.frameTimelinesLength; i++) {
VsyncEventData::FrameTimeline& frameTimeline = vsyncEventData.frameTimelines[i];
ScopedLocalRef<jobject>
frameTimelineObj(env, env->GetObjectArrayElement(frameTimelinesObj.get(), i));
env->SetLongField(frameTimelineObj.get(),
gDisplayEventReceiverClassInfo.frameTimelineClassInfo.vsyncId,
frameTimeline.vsyncId);
env->SetLongField(frameTimelineObj.get(),
gDisplayEventReceiverClassInfo.frameTimelineClassInfo
.expectedPresentationTime,
frameTimeline.expectedPresentationTime);
env->SetLongField(frameTimelineObj.get(),
gDisplayEventReceiverClassInfo.frameTimelineClassInfo.deadline,
frameTimeline.deadlineTimestamp);
}
// 调用 Java 层 DisplayEventReceiver 的 dispatchVsync() 方法
env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync,
timestamp, displayId.value, count);
ALOGV("receiver %p ~ Returned from vsync handler.", this);
}
mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// /frameworks/base/core/java/android/view/DisplayEventReceiver.java
private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) {
onVsync(timestampNanos, physicalDisplayId, frame, mVsyncEventData);
}
1
2
3
4
2
3
4
onVsync 实现在子类 FrameDisplayEventReceiver 中:
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
private final VsyncEventData mLastVsyncEventData = new VsyncEventData();
FrameDisplayEventReceiver(Looper looper, int vsyncSource, long layerHandle) {
super(looper, vsyncSource, /* eventRegistration */ 0, layerHandle);
}
// TODO(b/116025192): physicalDisplayId is ignored because SF only emits VSYNC events for
// the internal display and DisplayEventReceiver#scheduleVsync only allows requesting VSYNC
// for the internal display implicitly.
@Override
public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
VsyncEventData vsyncEventData) {
try {
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW,
"Choreographer#onVsync "
+ vsyncEventData.preferredFrameTimeline().vsyncId);
}
// Post the vsync event to the Handler.
// The idea is to prevent incoming vsync events from completely starving
// the message queue. If there are no messages in the queue with timestamps
// earlier than the frame time, then the vsync event will be processed immediately.
// Otherwise, messages that predate the vsync event will be handled first.
long now = System.nanoTime();
if (timestampNanos > now) {
Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
+ " ms in the future! Check that graphics HAL is generating vsync "
+ "timestamps using the correct timebase.");
timestampNanos = now;
}
if (mHavePendingVsync) {
Log.w(TAG, "Already have a pending vsync event. There should only be "
+ "one at a time.");
} else {
mHavePendingVsync = true;
}
mTimestampNanos = timestampNanos;
mFrame = frame;
mLastVsyncEventData.copyFrom(vsyncEventData);
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
@Override
public void run() {
mHavePendingVsync = false;
// 回调到 doFrame
doFrame(mTimestampNanos, mFrame, mLastVsyncEventData);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
重点 Choreographer#doFrame :
// /frameworks/base/core/java/android/view/Choreographer.java
void doFrame(long frameTimeNanos, int frame,
DisplayEventReceiver.VsyncEventData vsyncEventData) {
final long startNanos;
final long frameIntervalNanos = vsyncEventData.frameInterval;
boolean resynced = false;
try {
FrameTimeline timeline = mFrameData.update(frameTimeNanos, vsyncEventData);
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
Trace.traceBegin(
Trace.TRACE_TAG_VIEW, "Choreographer#doFrame " + timeline.mVsyncId);
}
synchronized (mLock) {
if (!mFrameScheduled) {
traceMessage("Frame not scheduled");
return; // no work to do
}
if (DEBUG_JANK && mDebugPrintNextFrameTimeDelta) {
mDebugPrintNextFrameTimeDelta = false;
Log.d(TAG, "Frame time delta: "
+ ((frameTimeNanos - mLastFrameTimeNanos) * 0.000001f) + " ms");
}
long intendedFrameTimeNanos = frameTimeNanos;
// 实际开始执行当前 frame 的时间
startNanos = System.nanoTime();
// 时间差
final long jitterNanos = startNanos - frameTimeNanos;
// // 时间差值大于等于帧间隔,即发生了掉帧
if (jitterNanos >= frameIntervalNanos) {
frameTimeNanos = startNanos;
if (frameIntervalNanos == 0) {
Log.i(TAG, "Vsync data empty due to timeout");
} else {
long lastFrameOffset = jitterNanos % frameIntervalNanos;
frameTimeNanos = frameTimeNanos - lastFrameOffset;
final long skippedFrames = jitterNanos / frameIntervalNanos;
// 掉帧时间超过 30 打印日志提醒,SKIPPED_FRAME_WARNING_LIMIT 通过读取
// 系统属性 debug.choreographer.skipwarning 来获取的,默认是 30
if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
Log.i(TAG, "Skipped " + skippedFrames + " frames! "
+ "The application may be doing too much work on its main "
+ "thread.");
}
if (DEBUG_JANK) {
Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms "
+ "which is more than the frame interval of "
+ (frameIntervalNanos * 0.000001f) + " ms! "
+ "Skipping " + skippedFrames + " frames and setting frame "
+ "time to " + (lastFrameOffset * 0.000001f)
+ " ms in the past.");
}
}
timeline = mFrameData.update(
frameTimeNanos, mDisplayEventReceiver, jitterNanos);
resynced = true;
}
if (frameTimeNanos < mLastFrameTimeNanos) {
if (DEBUG_JANK) {
Log.d(TAG, "Frame time appears to be going backwards. May be due to a "
+ "previously skipped frame. Waiting for next vsync.");
}
traceMessage("Frame time goes backward");
// 当前帧的时间小于上一个帧的时间,可能是由于先前掉帧的缘故,申请并等待下一次 VSync 信号到来
scheduleVsyncLocked();
return;
}
if (mFPSDivisor > 1) {
long timeSinceVsync = frameTimeNanos - mLastFrameTimeNanos;
if (timeSinceVsync < (frameIntervalNanos * mFPSDivisor) && timeSinceVsync > 0) {
traceMessage("Frame skipped due to FPSDivisor");
// 由于 FPSDivisor 导致跳帧,继续申请并等待下一次 VSync 信号到来
scheduleVsyncLocked();
return;
}
}
// 记录当前 Frame 信息
mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos,
vsyncEventData.preferredFrameTimeline().vsyncId,
vsyncEventData.preferredFrameTimeline().deadline, startNanos,
vsyncEventData.frameInterval);
mFrameScheduled = false;
mLastFrameTimeNanos = frameTimeNanos;
mLastFrameIntervalNanos = frameIntervalNanos;
mLastVsyncEventData.copyFrom(vsyncEventData);
}
if (resynced && Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
String message = String.format("Choreographer#doFrame - resynced to %d in %.1fms",
timeline.mVsyncId, (timeline.mDeadlineNanos - startNanos) * 0.000001f);
Trace.traceBegin(Trace.TRACE_TAG_VIEW, message);
}
AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
// 回调
mFrameInfo.markInputHandlingStart();
doCallbacks(Choreographer.CALLBACK_INPUT, frameIntervalNanos);
mFrameInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameIntervalNanos);
doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameIntervalNanos);
mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameIntervalNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT, frameIntervalNanos);
} finally {
AnimationUtils.unlockAnimationClock();
if (resynced) {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
if (DEBUG_FRAMES) {
final long endNanos = System.nanoTime();
Log.d(TAG, "Frame " + frame + ": Finished, took "
+ (endNanos - startNanos) * 0.000001f + " ms, latency "
+ (startNanos - frameTimeNanos) * 0.000001f + " ms.");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
void doCallbacks(int callbackType, long frameIntervalNanos) {
CallbackRecord callbacks;
long frameTimeNanos = mFrameData.mFrameTimeNanos;
synchronized (mLock) {
// We use "now" to determine when callbacks become due because it's possible
// for earlier processing phases in a frame to post callbacks that should run
// in a following phase, such as an input event that causes an animation to start.
final long now = System.nanoTime();
callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
now / TimeUtils.NANOS_PER_MS);
if (callbacks == null) {
return;
}
mCallbacksRunning = true;
// Update the frame time if necessary when committing the frame.
// We only update the frame time if we are more than 2 frames late reaching
// the commit phase. This ensures that the frame time which is observed by the
// callbacks will always increase from one frame to the next and never repeat.
// We never want the next frame's starting frame time to end up being less than
// or equal to the previous frame's commit frame time. Keep in mind that the
// next frame has most likely already been scheduled by now so we play it
// safe by ensuring the commit time is always at least one frame behind.
if (callbackType == Choreographer.CALLBACK_COMMIT) {
final long jitterNanos = now - frameTimeNanos;
Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos);
if (jitterNanos >= 2 * frameIntervalNanos) {
final long lastFrameOffset = jitterNanos % frameIntervalNanos
+ frameIntervalNanos;
if (DEBUG_JANK) {
Log.d(TAG, "Commit callback delayed by " + (jitterNanos * 0.000001f)
+ " ms which is more than twice the frame interval of "
+ (frameIntervalNanos * 0.000001f) + " ms! "
+ "Setting frame time to " + (lastFrameOffset * 0.000001f)
+ " ms in the past.");
mDebugPrintNextFrameTimeDelta = true;
}
frameTimeNanos = now - lastFrameOffset;
mLastFrameTimeNanos = frameTimeNanos;
mFrameData.update(frameTimeNanos, mDisplayEventReceiver, jitterNanos);
}
}
}
try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);
for (CallbackRecord c = callbacks; c != null; c = c.next) {
if (DEBUG_FRAMES) {
Log.d(TAG, "RunCallback: type=" + callbackType
+ ", action=" + c.action + ", token=" + c.token
+ ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));
}
// 执行 callback
c.run(mFrameData);
}
} finally {
synchronized (mLock) {
mCallbacksRunning = false;
do {
final CallbackRecord next = callbacks.next;
recycleCallbackLocked(callbacks);
callbacks = next;
} while (callbacks != null);
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66