Android VSYNC详解

来源:互联网 发布:nginx获取http header 编辑:程序博客网 时间:2024/05/06 05:51

Android UI层的刷新界面数据和SurfaceFlinger将显示数据刷新到屏幕,都依赖VSYNC信号。
VSYNC信号来自LCD模块,先看一下SurfaceFlinger加载LCD模块生成VSYNC信号回调到SurfaceFlinger的过程。

void SurfaceFlinger::init() {    ALOGI(  "SurfaceFlinger's main thread ready to run. "            "Initializing graphics H/W...");     status_t err;    Mutex::Autolock _l(mStateLock); ....     // Initialize the H/W composer object.  There may or may not be an    // actual hardware composer underneath.    mHwc = new HWComposer(this,            *static_cast<HWComposer::EventHandler *>(this));     // First try to get an ES2 config    err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT,            &mEGLConfig);     if (err != NO_ERROR) {        // If ES2 fails, try ES1        err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(),                EGL_OPENGL_ES_BIT, &mEGLConfig);    }     if (err != NO_ERROR) {        // still didn't work, probably because we're on the emulator...        // try a simplified query        ALOGW("no suitable EGLConfig found, trying a simpler query");        err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig);    }     if (err != NO_ERROR) {        // this EGL is too lame for android        LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");    } ....     // initialize our non-virtual displays    for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);        // set-up the displays that are already connected        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {            // All non-virtual displays are currently considered secure.            bool isSecure = true;            createBuiltinDisplayLocked(type);            wp<IBinder> token = mBuiltinDisplays[i];             sp<BufferQueue> bq = new BufferQueue(new GraphicBufferAlloc());            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, bq);            sp<DisplayDevice> hw = new DisplayDevice(this,                    type, allocateHwcDisplayId(type), isSecure, token,                    fbs, bq,                    mEGLConfig);            if (i > DisplayDevice::DISPLAY_PRIMARY) {                // FIXME: currently we don't get blank/unblank requests                // for displays other than the main display, so we always                // assume a connected display is unblanked.                ALOGD("marking display %d as acquired/unblanked", i);                hw->acquireScreen();            }            mDisplays.add(token, hw);        }    }     // make the GLContext current so that we can create textures when creating Layers    // (which may happens before we render something)    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);     // start the EventThread    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,            vsyncPhaseOffsetNs, true);    mEventThread = new EventThread(vsyncSrc);    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,            sfVsyncPhaseOffsetNs, false);    mSFEventThread = new EventThread(sfVsyncSrc);    mEventQueue.setEventThread(mSFEventThread);     mEventControlThread = new EventControlThread(this);    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);     // set a fake vsync period if there is no HWComposer    if (mHwc->initCheck() != NO_ERROR) {        mPrimaryDispSync.setPeriod(16666667);    }     // initialize our drawing state    mDrawingState = mCurrentState;     // set initial conditions (e.g. unblank default device)    initializeDisplays();     // start boot animation    startBootAnim();}

在HWC的构造函数中会加载HWC模块

.... HWComposer::HWComposer(        const sp<SurfaceFlinger>& flinger,        EventHandler& handler)    : mFlinger(flinger),      mFbDev(0), mHwc(0), mNumDisplays(1),      mCBContext(new cb_context),      mEventHandler(handler),      mDebugForceFakeVSync(false){....     // Note: some devices may insist that the FB HAL be opened before HWC.    int fberr = loadFbHalModule();    loadHwcModule();     if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {        // close FB HAL if we don't needed it.        // FIXME: this is temporary until we're not forced to open FB HAL        // before HWC.        framebuffer_close(mFbDev);        mFbDev = NULL;    }     // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.    if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))            && !mFbDev) {        ALOGE("ERROR: failed to open framebuffer (%s), aborting",                strerror(-fberr));        abort();    }     // these display IDs are always reserved    for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {        mAllocatedDisplayIDs.markBit(i);    }     if (mHwc) {        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,              (hwcApiVersion(mHwc) >> 24) & 0xff,              (hwcApiVersion(mHwc) >> 16) & 0xff);        if (mHwc->registerProcs) {            mCBContext->hwc = this;            mCBContext->procs.invalidate = &hook_invalidate;            mCBContext->procs.vsync = &hook_vsync;            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))                mCBContext->procs.hotplug = &hook_hotplug;            else                mCBContext->procs.hotplug = NULL;            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));            mHwc->registerProcs(mHwc, &mCBContext->procs);        }         // don't need a vsync thread if we have a hardware composer        needVSyncThread = false;        // always turn vsync off when we start        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);         // the number of displays we actually have depends on the        // hw composer version        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {            // 1.3 adds support for virtual displays            mNumDisplays = MAX_HWC_DISPLAYS;        } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {            // 1.1 adds support for multiple displays            mNumDisplays = NUM_BUILTIN_DISPLAYS;        } else {            mNumDisplays = 1;        }    }     if (mFbDev) {        ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),                "should only have fbdev if no hwc or hwc is 1.0");         DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);        disp.connected = true;        disp.width = mFbDev->width;        disp.height = mFbDev->height;        disp.format = mFbDev->format;        disp.xdpi = mFbDev->xdpi;        disp.ydpi = mFbDev->ydpi;        if (disp.refresh == 0) {            disp.refresh = nsecs_t(1e9 / mFbDev->fps);            ALOGW("getting VSYNC period from fb HAL: %lld", disp.refresh);        }        if (disp.refresh == 0) {            disp.refresh = nsecs_t(1e9 / 60.0);            ALOGW("getting VSYNC period from thin air: %lld",                    mDisplayData[HWC_DISPLAY_PRIMARY].refresh);        }    } else if (mHwc) {        // here we're guaranteed to have at least HWC 1.1        for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {            queryDisplayProperties(i);        }    }     if (needVSyncThread) {        // we don't have VSYNC support, we need to fake it        mVSyncThread = new VSyncThread(*this);    }} ....// Load and prepare the hardware composer module.  Sets mHwc.void HWComposer::loadHwcModule(){    hw_module_t const* module;    //Hardware??? module? ?????.    if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {        ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID);        return;    }    //?? ???? ?? ??? module? ?? HWComposer? ?????.    int err = hwc_open_1(module, &mHwc);    if (err) {        ALOGE("%s device failed to initialize (%s)",              HWC_HARDWARE_COMPOSER, strerror(-err));        return;    }    if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||            hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||            hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {        ALOGE("%s device version %#x unsupported, will not be used",              HWC_HARDWARE_COMPOSER, mHwc->common.version);        hwc_close_1(mHwc);        mHwc = NULL;        return;    }} ....int hw_get_module_by_class(const char *class_id, const char *inst,                           const struct hw_module_t **module){    int status;    int i;    const struct hw_module_t *hmi = NULL;    char prop[PATH_MAX];    char path[PATH_MAX];    char name[PATH_MAX];     if (inst)        snprintf(name, PATH_MAX, "%s.%s", class_id, inst);    else        strlcpy(name, class_id, PATH_MAX);     /*     * Here we rely on the fact that calling dlopen multiple times on     * the same .so will simply increment a refcount (and not load     * a new copy of the library).     * We also assume that dlopen() is thread-safe.     */     /* Loop through the configuration variants looking for a module */    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {        if (i < HAL_VARIANT_KEYS_COUNT) {            if (property_get(variant_keys[i], prop, NULL) == 0) {                continue;            }            snprintf(path, sizeof(path), "%s/%s.%s.so",                     HAL_LIBRARY_PATH2, name, prop);            if (access(path, R_OK) == 0) break;             snprintf(path, sizeof(path), "%s/%s.%s.so",                     HAL_LIBRARY_PATH1, name, prop);            if (access(path, R_OK) == 0) break;        } else {            snprintf(path, sizeof(path), "%s/%s.default.so",                     HAL_LIBRARY_PATH2, name);            if (access(path, R_OK) == 0) break;             snprintf(path, sizeof(path), "%s/%s.default.so",                     HAL_LIBRARY_PATH1, name);            if (access(path, R_OK) == 0) break;        }    }     status = -ENOENT;    if (i < HAL_VARIANT_KEYS_COUNT+1) {        /* load the module, if this fails, we're doomed, and we should not try         * to load a different variant. */        status = load(class_id, path, module);    }     return status;} int hw_get_module(const char *id, const struct hw_module_t **module){    return hw_get_module_by_class(id, NULL, module);}/** * Load the file defined by the variant and if successful * return the dlopen handle and the hmi. * @return 0 = success, !0 = failure. */static int load(const char *id,        const char *path,        const struct hw_module_t **pHmi){    int status;    void *handle;    struct hw_module_t *hmi;     /*     * load the symbols resolving undefined symbols before     * dlopen returns. Since RTLD_GLOBAL is not or'd in with     * RTLD_NOW the external symbols will not be global     */    handle = dlopen(path, RTLD_NOW);    if (handle == NULL) {        char const *err_str = dlerror();        ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");        status = -EINVAL;        goto done;    }     /* Get the address of the struct hal_module_info. */    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;    hmi = (struct hw_module_t *)dlsym(handle, sym);    if (hmi == NULL) {        ALOGE("load: couldn't find symbol %s", sym);        status = -EINVAL;        goto done;    }     /* Check that the id matches */    if (strcmp(id, hmi->id) != 0) {        ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);        status = -EINVAL;        goto done;    }     hmi->dso = handle;     /* success */    status = 0;     done:    if (status != 0) {        hmi = NULL;        if (handle != NULL) {            dlclose(handle);            handle = NULL;        }    } else {        ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",                id, path, *pHmi, handle);    }     *pHmi = hmi;     return status;}

以上dlsym()函数负责加载动态库。然后再通过hwc_open_1()函数调用module库中对应的open函数,也就是hwc_device_open()函数

static inline int hwc_open_1(const struct hw_module_t* module,        hwc_composer_device_1_t** device) {    return module->methods->open(module,            HWC_HARDWARE_COMPOSER, (struct hw_device_t**)device);} static inline int hwc_close_1(hwc_composer_device_1_t* device) {    return device->common.close(&device->common);}....static int hwc_device_open(const struct hw_module_t* module, const char* name,                           struct hw_device_t** device){    int status = -EINVAL;     if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {        struct hwc_context_t *dev;        dev = (hwc_context_t*)malloc(sizeof(*dev));        memset(dev, 0, sizeof(*dev));         //Initialize hwc context        initContext(dev);         //Setup HWC methods        dev->device.common.tag          = HARDWARE_DEVICE_TAG;        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_2;        dev->device.common.module       = const_cast<hw_module_t*>(module);        dev->device.common.close        = hwc_device_close;        dev->device.prepare             = hwc_prepare;        dev->device.set                 = hwc_set;        dev->device.eventControl        = hwc_eventControl;        dev->device.blank               = hwc_blank;        dev->device.query               = hwc_query;        dev->device.registerProcs       = hwc_registerProcs;        dev->device.dump                = hwc_dump;        dev->device.getDisplayConfigs   = hwc_getDisplayConfigs;        dev->device.getDisplayAttributes = hwc_getDisplayAttributes;        *device = &dev->device.common;        status = 0;    }    return status;}

然后通过回调函数调用到hwc_registerProcs函数注册vsync相关

/* * Save callback functions registered to HWC */static void hwc_registerProcs(struct hwc_composer_device_1* dev,                              hwc_procs_t const* procs){    ALOGI("%s", __FUNCTION__);    hwc_context_t* ctx = (hwc_context_t*)(dev);    if(!ctx) {        ALOGE("%s: Invalid context", __FUNCTION__);        return;    }    ctx->proc = procs;     // Now that we have the functions needed, kick off    // the uevent & vsync threads    init_uevent_thread(ctx);    init_vsync_thread(ctx);}void init_vsync_thread(hwc_context_t* ctx){    int ret;    pthread_t vsync_thread;    ALOGI("Initializing VSYNC Thread");    ret = pthread_create(&vsync_thread, NULL, vsync_loop, (void*) ctx);    if (ret) {        ALOGE("%s: failed to create %s: %s", __FUNCTION__,              HWC_VSYNC_THREAD_NAME, strerror(ret));    }}static void *vsync_loop(void *param){    const char* vsync_timestamp_fb0 = "/sys/class/graphics/fb0/vsync_event";    const char* vsync_timestamp_fb1 = "/sys/class/graphics/fb1/vsync_event";    int dpy = HWC_DISPLAY_PRIMARY;     hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param);     char thread_name[64] = HWC_VSYNC_THREAD_NAME;    prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY +                android::PRIORITY_MORE_FAVORABLE);     const int MAX_DATA = 64;    static char vdata[MAX_DATA];     uint64_t cur_timestamp=0;    ssize_t len = -1;    int fd_timestamp = -1;    int ret = 0;    bool fb1_vsync = false;    bool logvsync = false;     char property[PROPERTY_VALUE_MAX];    if(property_get("debug.hwc.fakevsync", property, NULL) > 0) {        if(atoi(property) == 1)            ctx->vstate.fakevsync = true;    }     if(property_get("debug.hwc.logvsync", property, 0) > 0) {        if(atoi(property) == 1)            logvsync = true;    }     /* Currently read vsync timestamp from drivers       e.g. VSYNC=41800875994       */    fd_timestamp = open(vsync_timestamp_fb0, O_RDONLY);    if (fd_timestamp < 0) {        // Make sure fb device is opened before starting this thread so this        // never happens.        ALOGE ("FATAL:%s:not able to open file:%s, %s",  __FUNCTION__,               (fb1_vsync) ? vsync_timestamp_fb1 : vsync_timestamp_fb0,               strerror(errno));        ctx->vstate.fakevsync = true;    }     do {        if (LIKELY(!ctx->vstate.fakevsync)) {            len = pread(fd_timestamp, vdata, MAX_DATA, 0);            if (len < 0) {                // If the read was just interrupted - it is not a fatal error                // In either case, just continue.                if (errno != EAGAIN &&                    errno != EINTR  &&                    errno != EBUSY) {                    ALOGE ("FATAL:%s:not able to read file:%s, %s",                           __FUNCTION__,                           vsync_timestamp_fb0, strerror(errno));                }                continue;            }            // extract timestamp            const char *str = vdata;            if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) {                cur_timestamp = strtoull(str + strlen("VSYNC="), NULL, 0);            }        } else {            usleep(16666);            cur_timestamp = systemTime();        }        // send timestamp to HAL        if(ctx->vstate.enable) {            ALOGD_IF (logvsync, "%s: timestamp %llu sent to HWC for %s",                      __FUNCTION__, cur_timestamp, "fb0");            ctx->proc->vsync(ctx->proc, dpy, cur_timestamp);        }     } while (true);    if(fd_timestamp >= 0)        close (fd_timestamp);     return NULL;}

在 /frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp中设置vsync函数

if (mHwc->registerProcs) {            mCBContext->hwc = this;            mCBContext->procs.invalidate = &hook_invalidate;            mCBContext->procs.vsync = &hook_vsync;            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))                mCBContext->procs.hotplug = &hook_hotplug;            else                mCBContext->procs.hotplug = NULL;            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));            mHwc->registerProcs(mHwc, &mCBContext->procs);        }void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,        int64_t timestamp) {    cb_context* ctx = reinterpret_cast<cb_context*>(            const_cast<hwc_procs_t*>(procs));    ctx->hwc->vsync(disp, timestamp);}void HWComposer::vsync(int disp, int64_t timestamp) {    if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {        {            Mutex::Autolock _l(mLock);             // There have been reports of HWCs that signal several vsync events            // with the same timestamp when turning the display off and on. This            // is a bug in the HWC implementation, but filter the extra events            // out here so they don't cause havoc downstream.            if (timestamp == mLastHwVSync[disp]) {                ALOGW("Ignoring duplicate VSYNC event from HWC (t=%lld)",                        timestamp);                return;            }             mLastHwVSync[disp] = timestamp;        }         char tag[16];        snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);        ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);         mEventHandler.onVSyncReceived(disp, timestamp);    }}

这里的onVSyncReceived就是SurfaceFlinger对应的onVSyncReceived函数

void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {    bool needsHwVsync = false;     { // Scope for the lock        Mutex::Autolock _l(mHWVsyncLock);        if (type == 0 && mPrimaryHWVsyncEnabled) {            needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);        }    }     if (needsHwVsync) {        enableHardwareVsync();    } else {        disableHardwareVsync(false);    }} ....void SurfaceFlinger::enableHardwareVsync() {    Mutex::Autolock _l(mHWVsyncLock);    if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {        mPrimaryDispSync.beginResync();        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);        mEventControlThread->setVsyncEnabled(true);        mPrimaryHWVsyncEnabled = true;    }}


在addResyncSample()函数中调用updateModel

bool DispSync::addResyncSample(nsecs_t timestamp) {    Mutex::Autolock lock(mMutex);    size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;    mResyncSamples[idx] = timestamp;    if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {        mNumResyncSamples++;    } else {        mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;    }    updateModelLocked();    if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) {        resetErrorLocked();    }    if (kIgnorePresentFences) {        // If we don't have the sync framework we will never have        // addPresentFence called.  This means we have no way to know whether        // or not we're synchronized with the HW vsyncs, so we just request        // that the HW vsync events be turned on whenever we need to generate        // SW vsync events.        return mThread->hasAnyEventListeners();    }    return mPeriod == 0 || mError > kErrorThreshold;}void DispSync::updateModelLocked() {    if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {        nsecs_t durationSum = 0;        for (size_t i = 1; i < mNumResyncSamples; i++) {            size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;            size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) % MAX_RESYNC_SAMPLES;            durationSum += mResyncSamples[idx] - mResyncSamples[prev];        }        mPeriod = durationSum / (mNumResyncSamples - 1);        double sampleAvgX = 0;        double sampleAvgY = 0;        double scale = 2.0 * M_PI / double(mPeriod);        for (size_t i = 0; i < mNumResyncSamples; i++) {            size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;            nsecs_t sample = mResyncSamples[idx];            double samplePhase = double(sample % mPeriod) * scale;            sampleAvgX += cos(samplePhase);            sampleAvgY += sin(samplePhase);        }        sampleAvgX /= double(mNumResyncSamples);        sampleAvgY /= double(mNumResyncSamples);        mPhase = nsecs_t(atan2(sampleAvgY, sampleAvgX) / scale);        if (mPhase < 0) {            mPhase += mPeriod;        }        if (kTraceDetailedInfo) {            ATRACE_INT64("DispSync:Period", mPeriod);            ATRACE_INT64("DispSync:Phase", mPhase);        }        // Artificially inflate the period if requested.        mPeriod += mPeriod * mRefreshSkipCount;        mThread->updateModel(mPeriod, mPhase);    }}void updateModel(nsecs_t period, nsecs_t phase) {        Mutex::Autolock lock(mMutex);        mPeriod = period;        mPhase = phase;        mCond.signal();}


然后在DispSync.cpp文件的threadLoop函数中在等待mCond信号完成。


    virtual bool threadLoop() {        status_t err;        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);        nsecs_t nextEventTime = 0;        while (true) {            Vector<CallbackInvocation> callbackInvocations;            nsecs_t targetTime = 0;            { // Scope for lock                Mutex::Autolock lock(mMutex);                if (mStop) {                    return false;                }                if (mPeriod == 0) {                    err = mCond.wait(mMutex);                    if (err != NO_ERROR) {                        ALOGE("error waiting for new events: %s (%d)",                                strerror(-err), err);                        return false;                    }                    continue;                }                nextEventTime = computeNextEventTimeLocked(now);                targetTime = nextEventTime;                bool isWakeup = false;                if (now < targetTime) {                    err = mCond.waitRelative(mMutex, targetTime - now);                    if (err == TIMED_OUT) {                        isWakeup = true;                    } else if (err != NO_ERROR) {                        ALOGE("error waiting for next event: %s (%d)",                                strerror(-err), err);                        return false;                    }                }                now = systemTime(SYSTEM_TIME_MONOTONIC);                if (isWakeup) {                    mWakeupLatency = ((mWakeupLatency * 63) +                            (now - targetTime)) / 64;                    if (mWakeupLatency > 500000) {                        // Don't correct by more than 500 us                        mWakeupLatency = 500000;                    }                    if (kTraceDetailedInfo) {                        ATRACE_INT64("DispSync:WakeupLat", now - nextEventTime);                        ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency);                    }                }                callbackInvocations = gatherCallbackInvocationsLocked(now);            }            if (callbackInvocations.size() > 0) {                fireCallbackInvocations(callbackInvocations);            }        }        return false;    }    void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {        for (size_t i = 0; i < callbacks.size(); i++) {//这里调用下面的代码段中初始化的两个DispSyncSource类对象的onDispSyncEvent回调函数            callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);        }    }void SurfaceFlinger::init() {    ...    // start the EventThread    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,            vsyncPhaseOffsetNs, true, "app");//这个是VSYNC-app    mEventThread = new EventThread(vsyncSrc);    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,            sfVsyncPhaseOffsetNs, true, "sf");//这个是VSYNC-sf    ...}

这样从fireCallbackInvocations()->SurfaceFlinger.cpp文件中DisSyncSource类的onDispSyncEvent()->EventThread.cpp的onVSyncEvent()

virtual void onDispSyncEvent(nsecs_t when) {        sp<VSyncSource::Callback> callback;        {            Mutex::Autolock lock(mCallbackMutex);            callback = mCallback;            if (mTraceVsync) {                mValue = (mValue + 1) % 2;                ATRACE_INT(mVsyncEventLabel.string(), mValue);//这个就是可以在systrace里边看到的            }        }        if (callback != NULL) {//            callback->onVSyncEvent(when);        }}void EventThread::onVSyncEvent(nsecs_t timestamp) {    Mutex::Autolock _l(mLock);    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;    mVSyncEvent[0].header.id = 0;    mVSyncEvent[0].header.timestamp = timestamp;    mVSyncEvent[0].vsync.count++;    mCondition.broadcast();}

看到这里又有一个mCondition,EventThread的threadLoop函数也在等待这个条件。具体看EventThread里边的threadLoop()->waitEvent()函数.


bool EventThread::threadLoop() {    DisplayEventReceiver::Event event;    Vector< sp<EventThread::Connection> > signalConnections;    signalConnections = waitForEvent(&event);    // dispatch events to listeners...    const size_t count = signalConnections.size();    for (size_t i=0 ; i<count ; i++) {        const sp<Connection>& conn(signalConnections[i]);        // now see if we still need to report this event        status_t err = conn->postEvent(event);        if (err == -EAGAIN || err == -EWOULDBLOCK) {            // The destination doesn't accept events anymore, it's probably            // full. For now, we just drop the events on the floor.            // FIXME: Note that some events cannot be dropped and would have            // to be re-sent later.            // Right-now we don't have the ability to do this.            ALOGW("EventThread: dropping event (%08x) for connection %p",                    event.header.type, conn.get());        } else if (err < 0) {            // handle any other error on the pipe as fatal. the only            // reasonable thing to do is to clean-up this connection.            // The most common error we'll get here is -EPIPE.            removeDisplayEventConnection(signalConnections[i]);        }    }    return true;}

waitEvent()函数里边,timstamp非0表示有vsync信号过来需要处理。然后再根据mDisplayEventConnections的大小来判断是否有client在等待vsync信号。
然后由此判断是否要使能vsync,或者根据timestamp判断是否等待目前的vsync处理完。最后返回一个signalConnections。

conn->postEvent()这个这里就是发vsync信号给对应的连接,目前android有surfaceflinger和Choreographoer两个在等待这个。


1.  下面看一下postEvent怎么传递消息给SurfaceFlinger的

status_t EventThread::Connection::postEvent(        const DisplayEventReceiver::Event& event) {    ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);    return size < 0 ? status_t(size) : status_t(NO_ERROR);}ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,        Event const* events, size_t count){    return BitTube::sendObjects(dataChannel, events, count);}

通过这里,最终调用到MessageQueue:cb_eventReceiver()

int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {    MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);    return queue->eventReceiver(fd, events);}int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {    ssize_t n;    DisplayEventReceiver::Event buffer[8];    while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {        for (int i=0 ; i<n ; i++) {            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {#if INVALIDATE_ON_VSYNC                mHandler->dispatchInvalidate();#else                mHandler->dispatchRefresh();#endif                break;            }        }    }    return 1;}

然后就是通过MessageQueue传递给SurfaceFlinger的onMessageReceived()函数

void MessageQueue::Handler::dispatchInvalidate() {    if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {        mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));    }}void MessageQueue::Handler::handleMessage(const Message& message) {    switch (message.what) {        case INVALIDATE:            android_atomic_and(~eventMaskInvalidate, &mEventMask);            mQueue.mFlinger->onMessageReceived(message.what);            break;        case REFRESH:            android_atomic_and(~eventMaskRefresh, &mEventMask);            mQueue.mFlinger->onMessageReceived(message.what);            break;        case TRANSACTION:            android_atomic_and(~eventMaskTransaction, &mEventMask);            mQueue.mFlinger->onMessageReceived(message.what);            break;    }}void SurfaceFlinger::onMessageReceived(int32_t what) {    ATRACE_CALL();    switch (what) {        case MessageQueue::TRANSACTION: {            handleMessageTransaction();            break;        }        case MessageQueue::INVALIDATE: {            bool refreshNeeded = handleMessageTransaction();            refreshNeeded |= handleMessageInvalidate();            refreshNeeded |= mRepaintEverything;            if (refreshNeeded) {                // Signal a refresh if a transaction modified the window state,                // a new buffer was latched, or if HWC has requested a full                // repaint                signalRefresh();            }            break;        }        case MessageQueue::REFRESH: {            handleMessageRefresh();            break;        }    }}


然后就是通过MessageQueue传递给SurfaceFlinger的onMessageReceived()函数


2. Choregrapher的部分

Choregrapher通过DisplayEventReceiver和NativeDisplayEventReceiver创建connection的过程可以参考http://blog.csdn.net/houliang120/article/details/50958212

最后反正就是从android_view_DisplayEventReceiver.cpp文件的handleEvent()->dispatchVsync()最终同步调用到FrameDisplayEventReceiver的onVsync()然后又异步调用到FrameDisplayEventReceiver的run函数。

看下面的onVsync函数中Message.obtain()函数传了this为参数,所以msg有了callback。在Handler.java的dispatchMessage()函数中可以看到,有了callback之后,就直接调用穿进去的runnable类型的run函数了,也就是FrameDisplayEventReceiver类型的run()函数

                                             
0 0
原创粉丝点击