天天看點

Android 應用程式請求VsyncApp Request Vsync

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();
    }
}
           

UML圖

Android 應用程式請求VsyncApp Request Vsync