App Request Vsync
/frameworks/base/core/java/android/view/ViewRootImpl.java
[ViewRootImpl.java–>ViewRootImpl.scheduleTraversals()]
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
/**
1. 建立一個mTraversalRunnable
2. 将mTraversalRunnable添加到Choreographer中CALLBACK_TRAVERSAL的消息隊列中
*/
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
[ViewRootImpl.java–>ViewRootImpl.mTraversalRunnable]
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
/frameworks/base/core/java/android/view/Choreographer.java
[Choreographer.java–>Choreographer.postCallback()]
/**
參數清單:
1. callbackType = Choreographer.CALLBACK_TRAVERSAL = 2
2. action = mTraversalRunnable
3. token = null
*/
public void postCallback(int callbackType, Runnable action, Object token) {
postCallbackDelayed(callbackType, action, token, );
}
/**
delay的時間
* delayMillis = 0
*/
public void postCallbackDelayed(int callbackType,
Runnable action, Object token, long delayMillis) {
if (action == null) {
throw new IllegalArgumentException("action must not be null");
}
/**
CALLBACK_LAST = CALLBACK_COMMIT = 3
*/
if (callbackType < || 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);
}
/**
1. 将action 添加到mCallbackQueues中Choreographer.CALLBACK_TRAVERSAL的隊列中
2. 由于dueTime = now + delayMillis = now,是以會執行scheduleFrameLocked
*/
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
if (dueTime <= now) {
scheduleFrameLocked(now);
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}
[Choreographer.java–>Choreographer.scheduleFrameLocked()]
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.
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();
} else {
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);
}
}
}
[Choreographer.java–>Choreographer.scheduleFrameLocked()]
private void scheduleVsyncLocked() {
mDisplayEventReceiver.scheduleVsync();
}
/frameworks/base/core/java/android/view/DisplayEventReceiver.java
[DisplayEventReceiver.java–>DisplayEventReceiver.scheduleVsync()]
/**
* Schedules a single vertical sync pulse to be delivered when the next
* display frame begins.
*/
public void scheduleVsync() {
if (mReceiverPtr == ) {
Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
+ "receiver has already been disposed.");
} else {
nativeScheduleVsync(mReceiverPtr);
}
}
/frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp
[android_view_DisplayEventReceiver.cpp–>android_view_DisplayEventReceiver.nativeScheduleVsync()]
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());
}
}
/frameworks/base/libs/androidfw/DisplayEventDispatcher.cpp
[DisplayEventDispatcher.cpp–>DisplayEventDispatcher::scheduleVsync()]
status_t DisplayEventDispatcher::scheduleVsync() {
if (!mWaitingForVsync) {
ALOGV("dispatcher %p ~ Scheduling vsync.", this);
// Drain all pending events.
nsecs_t vsyncTimestamp;
int32_t vsyncDisplayId;
uint32_t vsyncCount;
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "",
this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
}
status_t status = mReceiver.requestNextVsync();
if (status) {
ALOGW("Failed to request next vsync, status=%d", status);
return status;
}
mWaitingForVsync = true;
}
return OK;
}
/frameworks/native/libs/gui/DisplayEventReceiver.cpp
[DisplayEventReceiver.cpp–>DisplayEventReceiver::requestNextVsync()]
status_t DisplayEventReceiver::requestNextVsync() {
if (mEventConnection != NULL) {
mEventConnection->requestNextVsync();
return NO_ERROR;
}
return NO_INIT;
}
/frameworks/native/libs/gui/IDisplayEventConnection.cpp
[IDisplayEventConnection.cpp–>BpDisplayEventConnection::requestNextVsync()]
virtual void requestNextVsync() {
Parcel data, reply;
data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
remote()->transact(REQUEST_NEXT_VSYNC, data, &reply, IBinder::FLAG_ONEWAY);
}
/frameworks/native/services/surfaceflinger/EventThread.cpp
[EventThread.cpp–>EventThread::Connection::requestNextVsync()]
void EventThread::Connection::requestNextVsync() {
mEventThread->requestNextVsync(this);
}
[EventThread.cpp–>EventThread::requestNextVsync()]
void EventThread::requestNextVsync(
const sp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock);
mFlinger.resyncWithRateLimit();
if (connection->count < ) {
connection->count = ;
mCondition.broadcast();
}
}