您的位置:首页 > 移动开发 > Android开发

Android 5.1 SurfaceFlinger --- Dispatching VSync events

2015-08-12 11:13 686 查看
surfaceflinger进程由init.rc启动:

service surfaceflinger /system/bin/surfaceflinger

接下来进到surfaceflinger的main()函数:

frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp

int main(int, char**) {
// When SF is launched in its own process, limit the number of
// binder threads to 4.
ProcessState::self()->setThreadPoolMaxThreadCount(4);

// start the thread pool
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();

// instantiate surfaceflinger
sp<SurfaceFlinger> flinger = new SurfaceFlinger();

#if defined(HAVE_PTHREADS)
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
#endif
set_sched_policy(0, SP_FOREGROUND);

// initialize before clients can connect
flinger->init();

// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);

// run in this thread
flinger->run();

return 0;
}


首先设置surfaceflinger进程的Binder线程数量为4,进程优先级是PRIORITY_URGENT_DISPLAY,这个优先级的设置在Display系统的很多地方都能看到。与此同时,创建了一个SurfaceFlinger对象,调用了对应的init()函数,将surfaceflinger注册到ServiceManager中去,并启动surfaceflinger线程。

其中的初始化操作在init()中:

void SurfaceFlinger::init() {
ALOGI(  "SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W...");

status_t err;
Mutex::Autolock _l(mStateLock);

/* Set the mask bit of the sigset to block the SIGPIPE signal */
sigset_t sigMask;
sigemptyset (&sigMask);
sigaddset(&sigMask, SIGPIPE);
sigprocmask(SIG_BLOCK, &sigMask, NULL);

// initialize EGL for the default display
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(mEGLDisplay, NULL, NULL);

// 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));

// get a RenderEngine for the given display / config (can't fail)
mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());

// retrieve the EGL context that was selected/created
mEGLContext = mRenderEngine->getEGLContext();

LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
"couldn't create EGLContext");

// 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) {
// query from hwc if the non-virtual display is secure.
bool isSecure = mHwc->isSecure(i);;
createBuiltinDisplayLocked(type, isSecure);
wp<IBinder> token = mBuiltinDisplays[i];

sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer,
new GraphicBufferAlloc());

sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
consumer);
int32_t hwcId = allocateHwcDisplayId(type);
sp<DisplayDevice> hw = new DisplayDevice(this,
type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
fbs, producer,
mRenderEngine->getEGLConfig());
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 %zu as acquired/unblanked", i);
hw->setPowerMode(HWC_POWER_MODE_NORMAL);
}
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, "app");
mEventThread = new EventThread(vsyncSrc);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
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();
}


一步步来看:

// 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));


初始化HWComposer,封装了厂商的HAL层实现,来看看它的构造函数:

frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp

HWComposer::HWComposer(
const sp<SurfaceFlinger>& flinger,
EventHandler& handler)
: mFlinger(flinger),
mFbDev(0), mHwc(0), mNumDisplays(1),
mCBContext(new cb_context),
mEventHandler(handler),
mDebugForceFakeVSync(false),
mVDSEnabled(false)
{
for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {
mLists[i] = 0;
}

for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
mLastHwVSync[i] = 0;
mVSyncCounts[i] = 0;
}

char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.no_hw_vsync", value, "0");
mDebugForceFakeVSync = atoi(value);

bool needVSyncThread = true;

// 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.format = mFbDev->format;
DisplayConfig config = DisplayConfig();
config.width = mFbDev->width;
config.height = mFbDev->height;
config.xdpi = mFbDev->xdpi;
config.ydpi = mFbDev->ydpi;
config.secure = true; //XXX: Assuming primary is always true
config.refresh = nsecs_t(1e9 / mFbDev->fps);
disp.configs.push_back(config);
disp.currentConfig = 0;
} 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);
}
}

// read system property for VDS solution
// This property is expected to be setup once during bootup
if( (property_get("persist.hwc.enable_vds", value, NULL) > 0) &&
((!strncmp(value, "1", strlen("1"))) ||
!strncasecmp(value, "true", strlen("true")))) {
//HAL virtual display is using VDS based implementation
mVDSEnabled = true;
}

if (needVSyncThread) {
// we don't have VSYNC support, we need to fake it
mVSyncThread = new VSyncThread(*this);
}
#ifdef QCOM_BSP
// Threshold Area to enable GPU Tiled Rect.
property_get("debug.hwc.gpuTiledThreshold", value, "1.9");
mDynThreshold = atof(value);
#endif
}


一开始做了一些初始化操作,然后加载对应的HAL,对应函数loadHwcModule():

// Load and prepare the hardware composer module.  Sets mHwc.
void HWComposer::loadHwcModule()
{
hw_module_t const* module;

if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID);
return;
}

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


实现并不复杂,只是获取到HWComposer对应的hw_module_t结构体,并对老版本做了兼容,mHwc保存真正的HWComposer对象,作为返回结果供接下来的调用使用。

回到SurfaceFlinger的init()函数,继续往下走:

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


首先判断mHwc->registerProcs是否为空,这是一个函数指针,可以到HAL层的实现里去查找:

hardware/qcom/display/msm8974/libhwcomposer/hwc.cpp(cm-12.1)

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));
if(dev == NULL)
return status;
memset(dev, 0, sizeof(*dev));

//Initialize hwc context
status = initContext(dev);
if (status < 0) {
free(dev);
return status;
}

//Setup HWC methods
dev->device.common.tag          = HARDWARE_DEVICE_TAG;
dev->device.common.version      = HWC_DEVICE_API_VERSION_1_4;
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.setPowerMode        = hwc_setPowerMode;
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;
dev->device.getActiveConfig     = hwc_getActiveConfig;
dev->device.setActiveConfig     = hwc_setActiveConfig;
*device = &dev->device.common;
status = 0;
}
return status;
}


可以看到hwc_composer_device_1里定义了很多函数指针,有eventControl,registerProcs,getDisplayConfigs等等,这样可以SurfaceFlinger可以通过预先规定好的接口,调用HAL层里的具体实现。

回到HWComposer::init(),很显然这里mHwc->registerProcs不为空,实际上指向了HAL层的hwc_registerProcs():

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


这两句比较有意思,看到后面可以发现这其实就是注册了vsync发生时的回调,在hwcomposer得到硬件发来的vsync,然后做进一步处理:

mCBContext->procs.vsync = &hook_vsync;
mHwc->registerProcs(mHwc, &mCBContext->procs);


那我们去hwc_registerProcs()里看看:

hardware/qcom/display/msm8974/libhwcomposer/hwc.cpp(cm-12.1)

/*
* 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);
}


先看看init_vsync_thread()函数:

hardware/qcom/display/msm8974/libhwcomposer/hwc_vsync.cpp

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


逻辑也比较简单,vsync_loop函数指针作为参数,创建了一个新的pthread,可以想到这个线程应该就是vsync发送线程,那就看看vsync_loop()函数:

hardware/qcom/display/msm8974/libhwcomposer/hwc_vsync.cpp

static void *vsync_loop(void *param)
{
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;
char vdata[MAX_DATA];
bool logvsync = false;

struct pollfd pfd[2];
int fb_fd[2];
uint64_t timestamp[2];
int num_displays;

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

if (ctx->mExtDisplay->getHDMIIndex() > 0)
num_displays = 2;
else
num_displays = 1;

char vsync_node_path[MAX_SYSFS_FILE_PATH];
for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
snprintf(vsync_node_path, sizeof(vsync_node_path),
"/sys/class/graphics/fb%d/vsync_event",
dpy == HWC_DISPLAY_PRIMARY ? 0 :
ctx->mExtDisplay->getHDMIIndex());
ALOGI("%s: Reading vsync for dpy=%d from %s", __FUNCTION__, dpy,
vsync_node_path);
fb_fd[dpy] = open(vsync_node_path, O_RDONLY);

if (fb_fd[dpy] < 0) {
// Make sure fb device is opened before starting this thread so this
// never happens.
ALOGE ("%s:not able to open vsync node for dpy=%d, %s",
__FUNCTION__, dpy, strerror(errno));
if (dpy == HWC_DISPLAY_PRIMARY) {
ctx->vstate.fakevsync = true;
break;
}
}
// Read once from the fds to clear the first notify
pread(fb_fd[dpy], vdata , MAX_DATA, 0);

pfd[dpy].fd = fb_fd[dpy];
if (pfd[dpy].fd >= 0)
pfd[dpy].events = POLLPRI | POLLERR;
}

if (LIKELY(!ctx->vstate.fakevsync)) {
do {
int err = poll(pfd, num_displays, -1);
if(err > 0) {
for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
if (pfd[dpy].revents & POLLPRI) {
int len = pread(pfd[dpy].fd, vdata, MAX_DATA, 0);
if (UNLIKELY(len < 0)) {
// If the read was just interrupted - it is not a
// fatal error. Just continue in this case
ALOGE ("%s: Unable to read vsync for dpy=%d : %s",
__FUNCTION__, dpy, strerror(errno));
continue;
}
// extract timestamp
if (!strncmp(vdata, "VSYNC=", strlen("VSYNC="))) {
timestamp[dpy] = strtoull(vdata + strlen("VSYNC="),
NULL, 0);
}
// send timestamp to SurfaceFlinger
ALOGD_IF (logvsync,
"%s: timestamp %llu sent to SF for dpy=%d",
__FUNCTION__, timestamp[dpy], dpy);
ctx->proc->vsync(ctx->proc, dpy, timestamp[dpy]);
}
}

} else {
ALOGE("%s: vsync poll failed errno: %s", __FUNCTION__,
strerror(errno));
continue;
}
} while (true);

} else {

//Fake vsync is used only when set explicitly through a property or when
//the vsync timestamp node cannot be opened at bootup. There is no
//fallback to fake vsync from the true vsync loop, ever, as the
//condition can easily escape detection.
//Also, fake vsync is delivered only for the primary display.
do {
usleep(16666);
timestamp[HWC_DISPLAY_PRIMARY] = systemTime();
ctx->proc->vsync(ctx->proc, HWC_DISPLAY_PRIMARY,
timestamp[HWC_DISPLAY_PRIMARY]);

} while (true);
}

for (int dpy = HWC_DISPLAY_PRIMARY; dpy <= HWC_DISPLAY_EXTERNAL; dpy++ ) {
if(fb_fd[dpy] >= 0)
close (fb_fd[dpy]);
}

return NULL;
}


值得一提的是,这个loop线程同样设置了线程的优先级:

setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY +
android::PRIORITY_MORE_FAVORABLE);


这个函数的逻辑也很清晰:等待vsync消息然后分发给每个display,调用callback:

for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
if (pfd[dpy].revents & POLLPRI) {
int len = pread(pfd[dpy].fd, vdata, MAX_DATA, 0);
if (UNLIKELY(len < 0)) {
// If the read was just interrupted - it is not a
// fatal error. Just continue in this case
ALOGE ("%s: Unable to read vsync for dpy=%d : %s",
__FUNCTION__, dpy, strerror(errno));
continue;
}
// extract timestamp
if (!strncmp(vdata, "VSYNC=", strlen("VSYNC="))) {
timestamp[dpy] = strtoull(vdata + strlen("VSYNC="),
NULL, 0);
}
// send timestamp to SurfaceFlinger
ALOGD_IF (logvsync,
"%s: timestamp %llu sent to SF for dpy=%d",
__FUNCTION__, timestamp[dpy], dpy);
ctx->proc->vsync(ctx->proc, dpy, timestamp[dpy]);
}
}


也就是在vsync event到来的时候,通过HAL层把事件传递给了hwcomposer对象。

于是我们回到HWComposer里,看看ctx->proc->vsync()也就是hook_vsync()的实现:

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=%" PRId64 ")",
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);
}
}


最关键的还是最后一句,mEventHandler其实就是HWComposer构造时候传进来的SurfaceFlinger对象,SurfaceFlinger继承了HWComposer::EventHandler,实现了onVsyncReceived()接口:

mEventHandler.onVSyncReceived(disp, timestamp);


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


SurfaceFlinger::onVSyncReceived对vsync事件做出响应,这里先不继续讨论。创建完HWComposer对象,回到SurfaceFlinger的init()函数,接下来创建一系列显示设备对象,并启动了两个EventThread:

// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc);
mEventQueue.setEventThread(mSFEventThread);


这里传入参数mPrimaryDispSync创建了两个虚拟的vsync源,分别名叫”VSYNC-app”和”VSYNC-sf”,其实不用查看代码,从systrace里我们就能很直观地看到这两个名称的线程。

先看看mPrimaryDispSync是起什么作用的,它是SurfaceFlinger的一个成员变量:

DispSync mPrimaryDispSync;


创建SurfaceFlinger对象的时候没有对mPrimaryDispSync进行显式初始化,因此调用默认的构造函数:

DispSync::DispSync() :
mRefreshSkipCount(0),
mThread(new DispSyncThread()) {

mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);

reset();
beginResync();

if (kTraceDetailedInfo) {
// If we're not getting present fences then the ZeroPhaseTracer
// would prevent HW vsync event from ever being turned off.
// Even if we're just ignoring the fences, the zero-phase tracing is
// not needed because any time there is an event registered we will
// turn on the HW vsync events.
if (!kIgnorePresentFences) {
addEventListener(0, new ZeroPhaseTracer());
}
}
}


很显然,在它构造的时候就会启动一个类型为DispSyncThread的新的线程mThread,调用mThread->run()实际上是创建了一个新的进程,并在这个线程内执行DispSyncThread的threadLoop()函数:

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


其中的主要内容是在计算时间,决定信号是否到来,该进行下一步操作,否则就在mCond上等待:

err = mCond.waitRelative(mMutex, targetTime - now);


那什么时候唤醒它呢?这就是前面提到的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);
}
}


其中mPrimaryDispSync.addResyncSample()在满足特定条件下会调用updateModelLocked():

frameworks/native/services/surfaceflinger/DispSync.cpp

bool DispSync::addResyncSample(nsecs_t timestamp) {
...

updateModelLocked();

...
}


并调用DispSync::updateModelLocked():

frameworks/native/services/surfaceflinger/DispSync.cpp

void DispSync::updateModelLocked() {
...
mThread->updateModel(mPeriod, mPhase);
...
}


最终DispSyncThread:updateModel(),唤醒线程:

void updateModel(nsecs_t period, nsecs_t phase) {
Mutex::Autolock lock(mMutex);
mPeriod = period;
mPhase = phase;
mCond.signal();
}


唤醒后,获取需要所有Listeners的回调列表

callbackInvocations = gatherCallbackInvocationsLocked(now);


frameworks/native/services/surfaceflinger/DispSync.cpp

Vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
Vector<CallbackInvocation> callbackInvocations;
nsecs_t ref = now - mPeriod;

for (size_t i = 0; i < mEventListeners.size(); i++) {
nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
ref);

if (t < now) {
CallbackInvocation ci;
ci.mCallback = mEventListeners[i].mCallback;
ci.mEventTime = t;
callbackInvocations.push(ci);
mEventListeners.editItemAt(i).mLastEventTime = t;
}
}

return callbackInvocations;
}


从这段代码里不难看出,从mEventListeners里找出合适的listener,封装成CallbackInvocation对象并作为返回值返回。

这时候有一个疑问,这些listener是什么时候加到mEventListeners里去的。答案是创建EventThread的时候。

// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc);
mEventQueue.setEventThread(mSFEventThread);


mEventThread和mSFEventThread均是强指针,因此在第一次引用的时候会调用:

void EventThread::onFirstRef() {
run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}


新启动一个名为EventThread的线程:

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


EventThread::waitForEvent()函数:

// Here we figure out if we need to enable or disable vsyncs
if (timestamp && !waitForVSync) {
// we received a VSYNC but we have no clients
// don't report it, and disable VSYNC events
disableVSyncLocked();
} else if (!timestamp && waitForVSync) {
// we have at least one client, so we want vsync enabled
// (TODO: this function is called right after we finish
// notifying clients of a vsync, so this call will be made
// at the vsync rate, e.g. 60fps.  If we can accurately
// track the current state we could avoid making this call
// so often.)
enableVSyncLocked();
}


timestamp表示上一次某一个display获取到的vsync的时间,在EventThread第一次执行到这里的时候,一切都还没有准备就绪,于是timestamp为0,执行这一个代码段:

else if (!timestamp && waitForVSync) {
// we have at least one client, so we want vsync enabled
// (TODO: this function is called right after we finish
// notifying clients of a vsync, so this call will be made
// at the vsync rate, e.g. 60fps.  If we can accurately
// track the current state we could avoid making this call
// so often.)
enableVSyncLocked();
}


enableVSyncLocked()最终会调用setVSyncEnabled()把当前这个DispSyncSource注册成DispSync的listener。

void EventThread::enableVSyncLocked() {
if (!mUseSoftwareVSync) {
// never enable h/w VSYNC when screen is off
if (!mVsyncEnabled) {
mVsyncEnabled = true;
mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this));
mVSyncSource->setVSyncEnabled(true);
}
}
mDebugVsyncEnabled = true;
sendVsyncHintOnLocked();
}

virtual void SurfaceFlinger::setVSyncEnabled(bool enable) {
// Do NOT lock the mutex here so as to avoid any mutex ordering issues
// with locking it in the onDispSyncEvent callback.
if (enable) {
status_t err = mDispSync->addEventListener(mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
strerror(-err), err);
}
//ATRACE_INT(mVsyncOnLabel.string(), 1);
} else {
status_t err = mDispSync->removeEventListener(
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error unregistering vsync callback: %s (%d)",
strerror(-err), err);
}
//ATRACE_INT(mVsyncOnLabel.string(), 0);
}
}


就这样,DispSync线程在收到VSync消息的时候就能回调两个虚拟vsync源DispSyncSource的onVSyncEvent()

void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
for (size_t i = 0; i < callbacks.size(); i++) {
callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
}
}


virtual void DispSyncSource::onDispSyncEvent(nsecs_t when) {
sp<VSyncSource::Callback> callback;
{
Mutex::Autolock lock(mMutex);
callback = mCallback;

if (mTraceVsync) {
mValue = (mValue + 1) % 2;
ATRACE_INT(mVsyncEventLabel.string(), mValue);
}
}

if (callback != NULL) {
callback->onVSyncEvent(when);
}
}


最后调用EventThread::onVSyncEvent():

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


唤醒EventThread(),并通过conn->postEvent()发送消息:

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);
…
}
return true;
}


因为我们在main(),也就是SurfaceFlinger中调用了SurfaceFlinger::run():

void SurfaceFlinger::run() {
do {
waitForEvent();
} while (true);
}

void SurfaceFlinger::waitForEvent() {
mEventQueue.waitMessage();
}


事实上,最后EventThread::onVSyncEvent()就是通过MessageQueue(socket)把消息发给了SurfaceFlinger主线程。

void MessageQueue::Handler::handleMessage(const Message& message) {
switch (message.what) {
...
case REFRESH:
android_atomic_and(~eventMaskRefresh, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
...
}

void SurfaceFlinger::onMessageReceived(int32_t what) {
ATRACE_CALL();
switch (what) {
...
case MessageQueue::REFRESH: {
handleMessageRefresh();
break;
}
}
}


就这样,VSync消息一步步传递回了SurfaceFlinger的主线程,接下来就是对vsync进行响应,刷新系统的显示了。值得注意的是,surfaceflinger的刷新是跟着mSFEventThread这个虚拟的VsyncSource走的,因为前面是这么设置的:

mEventQueue.setEventThread(mSFEventThread)


所以vsync事件在线程中的传递流程大致如下:

HAL Thread-DispSyncThread - EventThread - SurfaceFlinger main Thread.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: