热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android7.1GUI系统vsync信号的产生和接收(五)

Vsync信号的产生。以下代码基于高通msm8909芯片,android7.1的源码。Vsync信号的产生有两种来源,一种是硬件,也就

Vsync信号的产生。

以下代码基于高通msm8909芯片,android7.1的源码。

Vsync信号的产生有两种来源,一种是硬件,也就是显示模块产生;一中是软件模拟,因为目前基本都是硬件产生的,所以软件模拟的代码就没有分析的必要了。

接下来分析由硬件产生的vsync是怎么传到surfaceflinger的。

这个硬件源就是HWComposer,它一方面管理这composerhal模块,composer模块是厂商定制UI合成的接口,我们通常不会直接操作HWComposer模块,而是通过surfaceflinger使用它;另一方面就是产生vsync信号。

简单介绍下HWComposer,有很多名字类似的文件,

frameworks/native/services/surfaceflinger/displayhardware/目录下的HWComposer.h,HWComposer.cpp这两个文件可以认为是硬件的抽象层,具体的硬件是指:hwcomposer(#defineHWC_HARDWARE_MODULE_ID"hwcomposer"),HWComposer.cpp文件是android提供的标准的api,具体到硬件平台可能会稍微有点区别,比如msm8909android7.1的代码根据宏定义:TARGET_USES_HWC2,实际加载的文件是HWComposer_hwc1.cpp,相应的surfaceflinger对应的文件是SurfaceFlinger_hwc1.cpp


Hardware/libhardware/include/hardware/Hwcomposer.h;

hardware/libhardware/modules/hwcomposer/Hwcomposer.cpp这两个文件是hwchal模块。

相应的lib库是libhwcomposer.msm8909,库的实现代码在hardware/qcom/display/libhwcompser目录下,主要文件有hwc.cpp,hwc_vsync.cpp,hwc_uevents.cpp,hwc_utils.cpp等。

下面先看下hwcomposer这个模块的加载,这个模块是由surfaceflinger来加载的:

SurfaceFlinger_hwc1.cpp,如下代码中,只列出与hwcomposer,与vsync有关的代码。

HWComposer* mHwc;
void SurfaceFlinger::init() {
//首先是启动EventThread线程, sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs这两个值都是1000000,在这两个值不等的情况下,会启动两个EventThread,一个是为surfaceflinger服务,一个是为有刷新UI需求的应用程序服务。这里走的是else。if (vsyncPhaseOffsetNs != sfVsyncPhaseOffsetNs) {}else{sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync,vsyncPhaseOffsetNs, true, "sf-app");mEventThread = new EventThread(vsyncSrc, *this);mEventQueue.setEventThread(mEventThread);}
//初始化一个HWComposer对象。其中的参数一个是surfaceflinger自身,另一个其实也是surfaceflinger自身,只是其类型转成了HWComposer::EventHandler,可见surfaceflinger一定继承自HWComposer::EventHandler,并实现了其中接口onVSyncReceived等。mHwc = DisplayUtils::getInstance()->getHWCInstance(this,*static_cast(this));
}


DisplayUtils.cpp
HWComposer* DisplayUtils::getHWCInstance(const sp& flinger,HWComposer::EventHandler& handler) @DisplayUtils.cpp{
//直接new了一个 HWComposer实例,转到其构造函数。return new HWComposer(flinger,handler);
}


HWComposer_hwc1.cpp
HWComposer::HWComposer(const sp& flinger,EventHandler& handler): mFlinger(flinger),mEventHandler(handler)...{
//首先加载FB的hal模块,对应设备用framebuffer_device_t* mFbDev表示;,然后加载Hwc模块,对应的设备用struct hwc_composer_device_1* mHwc表示。int fberr = loadFbHalModule();loadHwcModule();
//这里注册硬件回调事件,这个事件就是vsync信号,先分析传入的参数 mCBContext->procs。if (mHwc) {if (mHwc->registerProcs) {
//设置回调事件对应的方法实现,mCBContext->procs.invalidate = &hook_invalidate;mCBContext->procs.vsync = &hook_vsync;
//注册硬件回调事件。mHwc->registerProcs(mHwc, &mCBContext->procs);}}
}


Hwc模块的加载、准备的过程:


HWComposer_hwc1.cpp
void HWComposer::loadHwcModule(){hw_module_t const* module;
//这里会加载相应的lib库, hw_get_module这个方法是上层使用者加载HAL库的通用入口,传入硬件模块的ID,在系统指定的目录加载正确的HAL库,以出参的形式的得到打开的硬件模块 module。if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {return;}
//调用硬件模块的open方法,打开指定的硬件设备,int err = hwc_open_1(module, &mHwc);
}


hardware/libhardware/include/hardware/hardware.h

//每一个硬件模块都会定义的一个数据结构,


typedef struct hw_module_t {
//每一个HAL库都会提供的一个方法methods,struct hw_module_methods_t* methods;
}hw_module_t;


typedef struct hw_module_methods_t {
//这个 methods的数据结构中只有一个函数指针变量open,用来打开指定的硬件设备。int (*open)(const struct hw_module_t* module, const char* id,struct hw_device_t** device);
} hw_module_methods_t;


针对HWComposer模块,其相应的open函数是hwc_device_open:

hwc.cpp

static struct hw_module_methods_t hwc_module_methods = {.open = hwc_device_open
};


//在打开这个hwc设备时,给很多函数指针赋了值,我们只关注dev->device.registerProcs = hwc_registerProcs;


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 contextinitContext(dev);//Setup HWC methodsdev->device.common.tag = HARDWARE_DEVICE_TAG;dev->device.common.version = HWC_DEVICE_API_VERSION_1_5;dev->device.common.module = const_cast(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;
}


然后分析注册硬件的回调的参数,这个参数mCBContext->procs会接收到hwc模块发出的vsync信号。

mCBContext的类型是cb_context*,定义如下:


HWComposer_hwc1.cpp
struct HWComposer::cb_context {
//callbacks由继承自 hwc_procs_t,接着看下 hwc_procs_t的定义。struct callbacks : public hwc_procs_t {void (*zero[4])(void);};callbacks procs;HWComposer* hwc;
};


hwc_procs_t的定义在hwcomposer.h中,


hwcomposer.h
typedef struct hwc_procs {
//invalidate会触发屏幕刷新,在invalidate被调用不久会调用prepare和set,但是不保证调用了invalidate屏幕就一定会刷新,比如之前屏幕已经刷新过了,就不会在刷新。void (*invalidate)(const struct hwc_procs* procs);
//vsync是分析这部分代码的目的,在收到一个vsync事件,并且HWC_EVENT_VSYNC是enabled的,这个vsync方法会被hwcomposer hal模块调用,其中的参数disp标示这个vsync事件是属于那个显示设备。void (*vsync)(const struct hwc_procs* procs, int disp, int64_t timestamp);
//在一个显示设备连接或断开时会调用hotplug,主显示设备一直都是连接的,这个方法不会被调用,主要是针对可热插拔的设备。void (*hotplug)(const struct hwc_procs* procs, int disp, int connected);
} hwc_procs_t;


分析完了HWComposer这边的参数,接着看下mHwc->registerProcs的实现,

hwc.cpp

//设置注册到HWC的回调函数。

static void hwc_registerProcs(struct hwc_composer_device_1* dev,hwc_procs_t const* procs)
{hwc_context_t* ctx = (hwc_context_t*)(dev);if(!ctx) {ALOGE("%s: Invalid context", __FUNCTION__);return;}
//vsync将通过proc会调到HWComposer的vsync函数。ctx->proc = procs;//当有回调函数注册时,会启动uevent,vsync两个线程。uevent线程跟屏幕invalidate有关。init_uevent_thread(ctx);init_vsync_thread(ctx);
}


//主要关注vsync线程的开启。


hwc_vsync.cpp

//创建一个线程,然后执行其vsync_loop方法。

void init_vsync_thread(hwc_context_t* ctx){int ret;pthread_t vsync_thread;ret = pthread_create(&vsync_thread, NULL, vsync_loop, (void*) ctx);
}


static void *vsync_loop(void *param){
//物理显示设备的个数。int num_displays = HWC_NUM_DISPLAY_TYPES – 1;
//如果系统属性指定使用模拟vsync,把ctx->vstate.fakevsync = true;if(property_get("debug.hwc.fakevsync", property, NULL) > 0) {ctx->vstate.fakevsync = true;}
//非模拟vsync的情况,当有多个显示设备时,对每个显示设备都要执行回调,发出通知。if (LIKELY(!ctx->vstate.fakevsync)) {do {for (int dpy = HWC_DISPLAY_PRIMARY; dpy //使用模拟vsync的情况,通常是明确通过属性设置了或在开机时vsync时间戳节点还没打开,这时候会使用模拟vsync,模拟vsync指发给主显示设备。do {usleep(16666);uint64_t timestamp = systemTime();
//这个回调就是执行的HWComposer的vsync方法。ctx->proc->vsync(ctx->proc, HWC_DISPLAY_PRIMARY, timestamp);}while(true)}
}


HWComposer_hwc1.cpp

HWComposer这边vsync的接收函数是:hook_vsync,前面贴出的HWComposer的构造函数的代码中:mCBContext->procs.vsync= &hook_vsync; hook_vsync又调用了HWComposervsync方法。


void HWComposer::vsync(int disp, int64_t timestamp) {
//HWComposer直接通过mEventHandler把vsync信号传到surfaceflinger。mEventHandler.onVSyncReceived(disp, timestamp);
}


//接着看surfaceflinger是如何处理vsync信号的。surfaceflinger中事件管理员是mEventQueue,

它是MessageQueue类型的对象,所以vsync信号肯定是要送到mEventQueue中的,是怎么送过去的呢?这个过程比想的稍微复杂了点。

SurfaceFlinger_hwc1.cpp
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {bool needsHwVsync = false;{ // Scope for the lockMutex::Autolock _l(mHWVsyncLock);if (type == 0 && mPrimaryHWVsyncEnabled) {needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);}}if (needsHwVsync) {enableHardwareVsync();} else {disableHardwareVsync(false);}
}


为了说清楚vsync的接收过程,还要看几个相关的类,从surfaceflinger的初始化开始。

void SurfaceFlinger::init() {sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync,vsyncPhaseOffsetNs, true, "sf-app");mEventThread = new EventThread(vsyncSrc, *this);mEventQueue.setEventThread(mEventThread);mHwc = DisplayUtils::getInstance()->getHWCInstance(this,*static_cast(this));mEventControlThread = new EventControlThread(this);mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
}


在这个初始化函数中,HWComposer前面已经分析过,接着简单介绍下几个类的主要功能。

1),mPrimaryDispSync实例的类型是DispSync,这个DispSync的主要作用是模拟软件的vsync源,在收到硬件模块hwc传来的vsync后,可能会disable掉硬件vsync源,不在执行回调HWComposer这边vsync的接收函数是:hook_vsync,控制硬件vsync源开、关的就是EventControlThread.cpp

DispSync在每次接收到硬件的vsync时,都会判断要不要继续使用硬件的vsync,这个判断的其中一个方法是addResyncSample,这个方法也是onVSyncReceived(SurfaceFlinger_hwc1.cpp中的vsync接收函数)中执行判断的依据。还有一个方法是addPresentFence,这个方法在surfaceflinger处理显示合成的后期会调用,判断是否要使用硬件hwcvsync


DispSyncswvsync信号,传给注册的监听者,是在线程的threadLoop循环中实现的。


virtual bool threadLoop() {nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);while (true) {
//计算下一次的vsync时间,如果这个时间还没到,就wait一段时间差,targetTime = computeNextEventTimeLocked(now);if (now //获取都有那些监听,然后调用其回调onDispSyncEvent。callbackInvocations = gatherCallbackInvocationsLocked(now);fireCallbackInvocations(callbackInvocations);}
}


2),接着EventControlThread怎样控制硬件vsync的开关。


bool EventControlThread::threadLoop() {
// mVsyncEnabled这个值在初始化 EventControlThread时赋值为false,bool vsyncEnabled = mVsyncEnabled;
//这里会去调用HWComposer的实现。mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC,mVsyncEnabled);
//在线程启动后,这个while循环会进入wait,直到调用它的setVsyncEnabled的方法把这个唤醒。初始化时mVsyncEnabled是false,那就是说线程刚启动时是把vsync关闭的,是后面初始化显示设备时通过 setVsyncEnabled打开了。while (true) {status_t err = mCond.wait(mMutex);if (err != NO_ERROR) {ALOGE("error waiting for new events: %s (%d)",strerror(-err), err);return false;}
//唤醒后,判断要不要重新设置vsync的开、关。if (vsyncEnabled != mVsyncEnabled) {mFlinger->eventControl(HWC_DISPLAY_PRIMARY,SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);vsyncEnabled = mVsyncEnabled;}}
//这里返回值是false,就是说这个线程的threadloop不会在被系统调用,换句话它他是一个单次循环,只是通过内部的while实现循环执行。return false;
}


接着看EventControlThread线程被唤醒的条件:


void EventControlThread::setVsyncEnabled(bool enabled) {Mutex::Autolock lock(mMutex);mVsyncEnabled = enabled;mCond.signal();
}


只要有人调用setVsyncEnabled,通过mCond.signal();都会唤醒这个线程。第一次启动时谁会调用这个方法打开硬件的vsync呢?


大致列出调用逻辑以下方法都在SurfaceFlinger_hwc1.cpp中。

void SurfaceFlinger::init() {
//显示相关的初始化,这个调用在EventControlThread线程运行起来之后。initializeDisplays();
}


通过异步消息,调用了onInitializeDisplays();


void SurfaceFlinger::initializeDisplays() {class MessageScreenInitialized : public MessageBase {virtual bool handler() {flinger->onInitializeDisplays();}};sp msg = new MessageScreenInitialized(this);postMessageAsync(msg);
}


void SurfaceFlinger::onInitializeDisplays() {
//这个方法在每次点亮屏幕时都会被调用,针对主显示屏来说,应该是每次点两屏,都会重新打开硬件模块hwc的vsync。setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
}


既然点亮屏时会enable硬件hwcvsync,息屏时也会disable硬件hwcvsync

void SurfaceFlinger::setPowerModeInternal(const sp& hw,int mode) {mEventThread->onScreenAcquired();resyncToHardwareVsync(true);
}


void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
//这里调用了EventControlThread中的 setVsyncEnabled,参数true,会enable硬件的vsync。同时注意这里的变量 mPrimaryHWVsyncEnabled = true,这个变量是 SurfaceFlinger::onVSyncReceived的中一个判断条件,在收到硬件hwc的vsync回调时,判断要不要disable硬件vsync。mEventControlThread->setVsyncEnabled(true);mPrimaryHWVsyncEnabled = true;
}


最后看看mFlinger->eventControl()是如何控制vsync的。

void SurfaceFlinger::eventControl(int disp, int event, int enabled) {ATRACE_CALL();
//直接调用了HWComposer_hwc1.cpp中的实现。getHwComposer().eventControl(disp, event, enabled);
}


void HWComposer::eventControl(int disp, int event, int enabled) @HWComposer_hwc1.cpp{err = mHwc->eventControl(mHwc, disp, event, enabled);
//根据enabled,让HWComposer::VSyncThread::VSyncThread线程wait或者唤醒。mVSyncThread->setEnabled(enabled);
}


mHwc->eventControl()最终的实现在hwc_vsync.cpp,通过IO命令控制硬件vsync

int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable)@hwc_vsync.cpp{ioctl(ctx->dpyAttr[dpy].fd, MSMFB_OVERLAY_VSYNC_CTRL, &enable);
}


3),DispSyncSource,这个类是SurfaceFlinger_hwc1.cpp的内部类,他的构造函数中持有DispSync的引用,即mDispSync,这个类的主要功能是通过mDispSync添加、删除对vsync(DispSync中的)的监听,并接收vsync(来自DispSync)回调。

这个函数虽然也叫vsyncenabled,实际只是向DispSync添加、删除对vsync的监听。


virtual void setVSyncEnabled(bool enable) @SurfaceFlinger_hwc1.cpp$DispSyncSource{if (enable) {status_t err = mDispSync->addEventListener(mName, mPhaseOffset,static_cast(this));}else{status_t err = mDispSync→removeEventListener(static_cast(this));}
}


DispSync注册的监听vsync的回调类型是DispSync::Callback,DispSyncSource继承了这个类,并实现了其中的方法onDispSyncEvent

DispSync会把软件vsync信号通过注册的监听,回调其onDispSyncEvent函数。

virtual void onDispSyncEvent(nsecs_t when) @SurfaceFlinger_hwc1.cpp$DispSyncSource{sp callback;callback = mCallback;callback->onVSyncEvent(when);
}


这里出现了VSyncSource::Callback的回调,vsync信号会传到VSyncSource::Callback类中的onVSyncEvent函数。

这个VSyncSource::Callback的实现具体是什么?

surfaceflinger的初始化(init()函数)中,有这么一句代码:


mEventThread = new EventThread(vsyncSrc, *this);

其中参数vsyncSrc就是DispSyncSource,所以接着看EventThread线程的实现。这个线程在他第一次被引用时,由其强指针的特性执行其onFirstRef方法,让这个线程运行起来,第一次被引用的地方就是紧接着实例化其对象的代码:

mEventQueue.setEventThread(mSFEventThread);

这里让surfaceflinger的消息管理员mEventQueue(MessageQueue)跟EventThread线程绑定,现在越来越接近目标了,还记得分析这段的目的是想弄明白vsync信号是怎么传到surfaceflingermEventQueue的。

bool EventThread::threadLoop() @EventThread.cpp{signalConnections = waitForEvent(&event);
}


waitForEvent会调用下面的enableVSyncLocked函数,然后通过DispSyncSourcesetCallback函数,设置一个类型是VSyncSource::Callback的回调,这个回调的实现端就是EventThread自身。


void EventThread::enableVSyncLocked() @EventThread.cpp{mVSyncSource->setCallback(static_cast(this));
}


所以前面DispSync会先把vsync信号通过回调传到DispSyncSourceonDispSyncEvent,最后在传到EventThreadonVSyncEvent函数。



4),EventThread是如何处理vsync信号的。

void EventThread::onVSyncEvent(nsecs_t timestamp) @EventThread.cpp{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();
}


上面的函数做了两件事情,一是填充了DisplayEventReceiver::Event类型的事件对象mVSyncEvent,主要包括事件的类型DisplayEventReceiver::DISPLAY_EVENT_VSYNC,还有事件戳timestamp。另外一个事情是mCondition.broadcast(),唤醒等待的EventThread线程。

EventThread线程什么情况下wait的呢?一种情况是没有对vsync感兴趣的客户端,另一种情况是正在等待vsync信号的产生,还有一种情况是当前屏幕是off,不需要vsync,这是会进入一个16ms的超时等待。

唤醒之后,线程继续循环。

bool EventThread::threadLoop() @EventThread.cpp{DisplayEventReceiver::Event event;Vector > signalConnections;
//线程就是在waitForEvent中进入等待的。signalConnections = waitForEvent(&event);
//开始分发vsync给所有的监听者,eventthread处理的事件不是只有vsync,还有DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG;const size_t count = signalConnections.size();for (size_t i=0 ; i& conn(signalConnections[i]);status_t err = conn->postEvent(event);}
//返回值true,系统会再次调用这个线程的threadloop,从而形成一个循环。return true;
}


waitForEvent除了会让线程进入wait,还有一个作用是找出等待事件的connections,也即是对vsync感兴趣的监听者,找出来后保存在signalConnections中。所有对vsync感兴趣的监听者都会被保存在mDisplayEventConnections中。

通常有两类监听者,


一类是surfaceflinger,它负责UI数据的合成,肯定要受vsync信号的触发。负责vsync接收的是surfaceflinger的事件管理员MessageQueue,相应的实例对象是mEventQueue,前面提到当实例化EventThread对象后,mEventQueue就跟EventThread执行了绑定,具体代码:


void MessageQueue::setEventThread(const sp& eventThread)
{mEventThread = eventThread;mEvents = eventThread->createEventConnection();mEventTube = mEvents->getDataChannel();mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT,MessageQueue::cb_eventReceiver, this);
}


首先通过eventThread的接口createEventConnection创建了一个Connection,赋值给mEvents,并且当这个Connection实例被引用时,会执行其onFirstRef方法,将这个Connection注册到EventThread中,把这个connection保存到EventThread中的变量mDisplayEventConnections中。


void EventThread::Connection::onFirstRef() {mEventThread->registerDisplayEventConnection(this);
}


mEvents的类型是sp,也即是Connection的客户端,对应的服务端的实现是EventThread的内部类Connection,这个可以从它的继承关系看出:

class Connection : public BnDisplayEventConnection {}

Connection继承了BnDisplayEventConnection

然后,通过mEvents获取一个mEventTube,这个BitTube的实质是socketpair,它有一个发送端,一个接收端。

最后通过mEventTube->getFd()获取了socketpair的接收端,并且给这个接收设置了回调MessageQueue::cb_eventReceiver,通过Looper接口addFd把他们加入到Looper中的监视请求列表mRequests,我们知道主线程循环从消息队列中取消息时,会调用LooperpollOnce,然后是pollInner,在这个pollInner中,只要有事件需要处理,就会执行其callback函数,在这个场景中,就会执行MessageQueue::cb_eventReceiver

弄清楚了事件的接收端,那事件的发送端在哪里呢?负责发送的服务端就是EventThread,具体实现就是下面的postEvent:


bool EventThread::threadLoop() {status_t err = conn->postEvent(event);
}


//mChannel就是前面说的BitTube,会通过其mSendFdevent数据写入。

status_t EventThread::Connection::postEvent(const DisplayEventReceiver::Event& event) {ssize_t size &#61; DisplayEventReceiver::sendEvents(mChannel, &event, 1);return size <0 ? status_t(size) : status_t(NO_ERROR);
}


第二类对vsync感兴趣的监听者是应用程序&#xff0c;不在详细分析&#xff0c;只把它创建connection的过程列一下。

每一个有窗口的应用进程&#xff0c;都会有一个渲染线程RenderThread&#xff0c;

frameworks/base/libs/hwui/renderthread/
bool RenderThread::threadLoop() &#64;RenderThread.cpp{initThreadLocals();
}


void RenderThread::initThreadLocals() {initializeDisplayEventReceiver();
}


//接收vsync的回调RenderThread::displayEventReceiverCallback,


void RenderThread::initializeDisplayEventReceiver() {mDisplayEventReceiver &#61; new DisplayEventReceiver();mLooper->addFd(mDisplayEventReceiver->getFd(), 0,Looper::EVENT_INPUT, RenderThread::displayEventReceiverCallback, this);
}


//先获取surfaceflinger的句柄

ISurfaceComposer

DisplayEventReceiver::DisplayEventReceiver() {sp sf(ComposerService::getComposerService());if (sf !&#61; NULL) {mEventConnection &#61; sf->createDisplayEventConnection();if (mEventConnection !&#61; NULL) {mDataChannel &#61; mEventConnection->getDataChannel();}}
}


//调用eventthread中接口createEventConnection

sp SurfaceFlinger::createDisplayEventConnection() {return mEventThread->createEventConnection();
}


sp EventThread::createEventConnection() const {return new Connection(const_cast(this));
}









推荐阅读
author-avatar
swa乄ycat曼颜
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有