Android系统Surface机制的SurfaceFlinger服务的线程模型分析_第1页
Android系统Surface机制的SurfaceFlinger服务的线程模型分析_第2页
Android系统Surface机制的SurfaceFlinger服务的线程模型分析_第3页
Android系统Surface机制的SurfaceFlinger服务的线程模型分析_第4页
Android系统Surface机制的SurfaceFlinger服务的线程模型分析_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、精选文档Android系统Surface机制的SurfaceFlinger服务的线程模型分析在前面两篇文章中,我们分析了SurfaceFlinger服务的启动过程以及SurfaceFlinger服务初始化硬件帧缓冲区的过程。从这两个过程可以知道,SurfaceFlinger服务在启动的过程中,一共涉及到了三种类型的线程,它们分别是Binder线程、UI渲染线程和把握台大事监控线程。在本文中,我们就将具体分SurfaceFlinger服务的线程模型,即上述三种类型的线程是如何运行和交互的。 从 一文可以知道,SurfaceFlinger服务是在System进程的主线程中启动的。System进程的

2、主线程在启动系统的关键服务之前,会先启动一个Binder线程池。这样运行在System进程中的系统关系服务就可以与其它进程执行Binder进程间通信了。SurfaceFlinger服务虽然是由System进程的主线程来负责启动的,但是最终它会运行在一个独立的线程中。我们将这个独立的线程称为UI渲染线程,由于它负责渲染系统的UI。 从 一文可以知道,SurfaceFlinger服务的UI渲染线程的启动的时候,会对系统的硬件帧缓冲区进行初始化。在初始化的过程,又会创建另外一个线程来监控硬件帧缓冲区的睡眠/唤醒状态切换大事。为了便利描述,我们这个线程称称为把握台大事监控线程。 上述的三种类型的线程的

3、启动挨次,可以通过图1来描述,如下所示:从图1就可以清楚地看到,System进程的主线程负责启动Binder线程池,以及UI渲染线程,而UI渲染线程又负责启动把握台大事监控线程。在这三种类型的线程中,UI渲染线程是主角,Binder线程和把握台大事监控线程是配角。Binder线程池是为了让其它进程,例如Android应用程序进程,可以与SurfaceFlinger服务进行Binder进程间通信的,有一部分通信所执行的操作便是让UI渲染线程更新系统的UI。把握台大事监控线程是为了监控硬件帧缓冲区的睡眠/唤醒状态切换大事的。一旦硬件帧缓冲区要进入睡眠或者唤醒状态,把握台大事监控线程都需要通知UI渲

4、染线程,以便UI渲染线程可以执行关闭或者启动显示屏的操作。 接下来,为了弄清楚SurfaceFlinger服务的线程模型,我们就首先简要分析UI渲染线程的运行模型,接着再分析Binder线程与UI渲染线程的交互过程,最终分析把握台大事监控线程与UI渲染线程的交互过程。 1. UI渲染线程的运行模型 在前面 一文中提到,SurfaceFlinger服务的UI渲染线程有一个消息队列。当消息队列为空时,SurfaceFlinger服务的UI渲染线程就会进入睡眠等待状态。一旦SurfaceFlinger服务的Binder线程接收到其它进程发送过来的渲染UI的恳求时,它就会往SurfaceFlinger

5、服务的UI渲染线程的消息队列中发送一个消息,以便可以将SurfaceFlinger服务的UI渲染线程唤醒起来执行渲染的操作。同样,一旦SurfaceFlinger服务的把握台大事监控线程发觉硬件帧缓冲区即将要进入睡眠或者唤醒状态时,它就会往SurfaceFlinger服务的UI渲染线程的消息队列中发送一个消息,以便SurfaceFlinger服务的UI渲染线程可以执行冻结或者解冻显示屏的操作。 从前面 一文又可以知道,SurfaceFlinger服务的UI渲染线程是以SurfaceFlinger类的成员函数threadLoop为线程执行体的,即SurfaceFlinger服务的UI渲染线程会不

6、断地循环执行SurfaceFlinger类的成员函数threadLoop。接下来,我们就通过SurfaceFlinger类的成员函数threadLoop的实现来分析SurfaceFlinger服务的UI渲染线程的运行模型,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片bool SurfaceFlinger:threadLoop() waitForEvent(); / check for transactions if (UNLIKELY(mConsoleSignals) handleConsoleEvents(); if (LIKELY(mTransa

7、ctionCount = 0) / if we're in a global transaction, don't do anything. const uint32_t mask = eTransactionNeeded | eTraversalNeeded; uint32_t transactionFlags = getTransactionFlags(mask); if (LIKELY(transactionFlags) handleTransaction(transactionFlags); / post surfaces (if needed) handlePageF

8、lip(); const DisplayHardware& hw(graphicPlane(0).displayHardware(); if (LIKELY(hw.canDraw() && !isFrozen() #ifdef USE_COMPOSITION_BYPASS if (handleBypassLayer() unlockClients(); return true; #endif / repaint the framebuffer (if needed) const int index = hw.getCurrentBufferIndex(); Graphi

9、cLog& logger(GraphicLog:getInstance(); logger.log(GraphicLog:SF_REPAINT, index); handleRepaint(); / inform the h/w that we're done compositing logger.log(GraphicLog:SF_COMPOSITION_COMPLETE, index); positionComplete(); logger.log(GraphicLog:SF_SWAP_BUFFERS, index); postFramebuffer(); logger.l

10、og(GraphicLog:SF_REPAINT_DONE, index); else / pretend we did the post positionComplete(); usleep(16667); / 60 fps period return true; 这个函数定义在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。 从前面 一文可以知道,SurfaceFlinger类的成员函数threadLoop的工作过程如下所示: 1. 调用SurfaceFlinger类的成员函数waitForEvent中检查Surf

11、aceFlinger服务的UI渲染线程的消息队列是否为空。假如不为空,那么就会马上返回来执行其它的操作,否则的话,SurfaceFlinger服务的UI渲染线程就会进入睡眠等状态,直到被SurfaceFlinger服务的Binder线程或者把握台大事监控线程唤醒为止。 2. 当SurfaceFlinger服务的UI渲染线程被把握台大事监控线程唤醒时,SurfaceFlinger类的成员变量mConsoleSignals的值就会不等于0。在这种状况下,SurfaceFlinger类的成员函数threadLoop就会调用另外一个成员函数handleConsoleEvents来处理把握台大事。后面在

12、分析SurfaceFlinger服务的UI渲染线程和把握台大事监控线程的交互过程时,我们再分析这个成员函数的实现。 3. SurfaceFlinger类的成员变量mTransactionCount用来描述SurfaceFlinger服务是否正在执行事务。假如SurfaceFlinger服务正在执行事务,那么SurfaceFlinger类的成员变量mTransactionCount的值就会大于0。怎么理解SurfaceFlinger服务所执行的事务是什么呢?这些事务是用来处理系统的显示属性的。这些属性划分为两种类型。一种类型是与整个显示屏属性相关的,例如屏幕旋转方向发生了变化,另一外类型是与某一

13、个应用程序的Surface相关的,例如某一个Surface的大小或者Z轴位置发生了变化。一般来说,每当系统的显示属性发生了变化的时候,SurfaceFlinger服务的UI渲染线程都需要马上刷新系统UI,以便可以反映真实状况。但是,为了削减屏幕的闪烁,有时候可以将多个属性变化组合成一个事务来刷新系统UI。例如,我们可以在修改了一个Surface的大小和Z轴位置之后,才要求SurfaceFlinger服务的UI渲染线程去刷新系统UI,这样就可以削减一个刷新系统UI的操作。因此,只有当SurfaceFlinger类的成员变量mTransactionCount的值的等于0的时候,SurfaceFli

14、nger类的成员函数threadLoop才会推断系统的显示属性是否发生了变化。假如发生了变化,那么就会调用另外一个成员函数handleTransaction来进一步处理。在接下来的一篇文章中分析SurfaceFlinger服务的UI渲染过程时,我们就具体分析这个成员函数的实现。 4. SurfaceFlinger服务的UI渲染线程接下来调用SurfaceFlinger类的成员函数handlePageFlip来通知各个应用程序的Surface将接下来要渲染的图形缓冲区设置为当前激活的图形缓冲区,以便接下来可以渲染到硬件帧缓冲区中去。我们同样会在接下来的一篇文章中分析SurfaceFlinger服

15、务的UI渲染过程时,具体分析这个成员函数的实现。 5. 假如SurfaceFlinger服务的UI渲染线程目前只有一个Surface需要渲染,并且SurfaceFlinger类在编译时,指定了USE_COMPOSITION_BYPASS宏,那么SurfaceFlinger类的成员函数threadLoop就会直接调用另外一个成员函数handleBypassLayer来将这个Surface直接渲染到硬件帧缓冲区中去。这是一个优化操作,避开执行接下来的Surface合成操作。 6. 假如SurfaceFlinger服务的UI渲染线程目前有多个Surface需要渲染,或者SurfaceFlinger类

16、在编译时没指定USE_COMPOSITION_BYPASS宏,那么SurfaceFlinger类的成员函数threadLoop接下来就会调用另外一个成员函数handleRepaint来将各个Surface的图形缓冲区合成起来,以便接下来可以渲染到硬件帧缓冲区中去。Surface的合成操作比较简单,由于它涉及到可见性计算等。我们同样会在接下来的一篇文章中分析SurfaceFlinger服务的UI渲染过程时,具体分析这个成员函数的实现。 7. 要渲染的各个Surface的图形缓冲区被合成之后,SurfaceFlinger类的成员函数threadLoop接下来前面获得的用来描述系统主显示屏的Disp

17、layHardware对象hw的成员函数compositionComplete来通知HAL层Gralloc模块中的fb设备,以便这个fb设备可以在Surface合成操作完成时执行一些规律。这一步是可选的,取决于HAL层Gralloc模块中的fb设备是否需要接收这个Surface合成完成通知。 8. 上述步骤都执行完成之后,SurfaceFlinger类的成员函数threadLoop最终就可以调用SurfaceFlinger类的成员函数postFramebuffer来将合成后得到的图形缓冲区渲染到硬件帧缓冲区去了,这样就可以将系统的最新UI渲染出来,或者说刷新了系统的UI。 在本小节中,我们只关

18、注第1步的处理过程,即SurfaceFlinger类的成员函数waitForEvent的实现,以便可以了解SurfaceFlinger服务的UI渲染线程是如何围绕它的消息队列来运行的。 SurfaceFlinger类的成员函数waitForEvent的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片void SurfaceFlinger:waitForEvent() while (true) nsecs_t timeout = -1; const nsecs_t freezeDisplayTimeout = ms2ns(5000); if (UNLI

19、KELY(isFrozen() / wait 5 seconds const nsecs_t now = systemTime(); if (mFreezeDisplayTime = 0) mFreezeDisplayTime = now; nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime); timeout = waitTime>0 ? waitTime : 0; sp<MessageBase> msg = mEventQueue.waitMessage(timeout); / see i

20、f we timed out if (isFrozen() const nsecs_t now = systemTime(); nsecs_t frozenTime = (now - mFreezeDisplayTime); if (frozenTime >= freezeDisplayTimeout) / we timed out and are still frozen LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d", mFreezeDisplay, mFreezeCount); mFreezeD

21、isplayTime = 0; mFreezeCount = 0; mFreezeDisplay = false; if (msg != 0) switch (msg->what) case MessageQueue:INVALIDATE: / invalidate message, just return to the main loop return; 这个函数定义在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。 在分析这个函数的实现之前,我们首先了解一下SurfaceFlinger类的三个成员变量mFre

22、ezeDisplay、mFreezeDisplayTime和mFreezeCount的含义。 外部进程,例如,应用程序进程,可以恳求SurfaceFlinger服务将显示屏冻结,这时候SurfaceFlinger类的成员变量mFreezeDisplay的值就会等于true。当显示屏被冻结时,SurfaceFlinger服务同时也会记录被冻结的起始时间,记录在SurfaceFlinger类的成员变量mFreezeDisplayTime中。另一方面,SurfaceFlinger服务在修改某一个Surface的显示属性时,例如,修改它的大小时,假如发觉显示屏此时正处于被冻结的状态,这时候就会将Sur

23、faceFlinger类的成员变量mFreezeCount的值增加1,表示这个Surface也需要冻结显示屏。 从SurfaceFlinger类的成员函数threadLoop的实现可以知道,SurfaceFlinger服务都会调用SurfaceFlinger类的另外一个成员函数isFrozen来推断显示屏是否处于冻结状态。假如是的话,那么SurfaceFlinger服务是不行以执行渲染UI的操作的。SurfaceFlinger类的成员函数isFrozen的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片class SurfaceFlinger : p

24、ublic BinderService<SurfaceFlinger>, public BnSurfaceComposer, protected Thread . private: . inline bool isFrozen() const return (mFreezeDisplay | mFreezeCount>0) && mBootFinished; . ; 这个函数定义在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.h中。 SurfaceFlinger类的另外一个成员变量mBootF

25、inished用来表示系统是否已经启动完成的。从前面 一文可以知道,当系统启动完成时,第三个开机画面,即开动动画,就会被停止,同时SurfaceFlinger类的成员变量mBootFinished的值会被设置为true。从SurfaceFlinger类的成员函数isFrozen的实现也可以看出,只有当系统启动完成之后,显示屏才会有冻结的概念。由于在系统启动的过程中,显示屏都是依次被三个开机画面独占的,而在独占的期间,不会消灭同时去修改显示属性的问题,因此就不需要去冻结显示屏。 由于将显示屏冻结的目的一般是为了修改显示屏的显示属性,例如修改某一个Surface的大小或者修改显示并的旋转方向等,因

26、此,通过SurfaceFlinger类的两个成员变量mFreezeDisplay和mFreezeCount,SurfaceFlinger服务就可以将多个显示属性变化合并在一起去渲染UI,避开单独为每一个显示属性变化执行一次UI渲染操作。单独为每一个显示属性变化执行一次UI渲染操作会消灭什么状况呢?假如有两个显示属性是同时发生变化的,那么执行两次UI渲染操作就会可能导致冲突,从而造成一些画面上的误差。 理解了SurfaceFlinger类的三个成员变量mFreezeDisplay、mFreezeDisplayTime和mFreezeCount的含义之后,接下来我们就可以分析SurfaceFlin

27、ger类的成员函数waitForEvent的实现了。 当消息队列为空时,SurfaceFlinger服务的UI渲染线程每一次进行睡眠等待状态的默认时间被设置为5000毫秒,保存在变量freezeDisplayTimeout中。但是假如显示屏当前正处于冻结状态,那么这个等待的时间就会从默认值减去已经被冻结的时间。这样做的目的是避开显示屏长时间被冻结而导致UI不能被渲染,即相当于是将显示屏的最长冻结时间设置为5000毫秒。 最终得到的等待时间就保存在变量timeout中,接下来SurfaceFlinger类的成员函数waitForEvent就会调用成员变量mEventQueue所描述的一个消息队列

28、的成员函数waitMessage来检查是否有新的消息需要处理。假如没有,那么SurfaceFlinger服务的UI渲染线程就会进入到睡眠等待状态中去,直到消息队列有新的消息需要处理或者等待超时为止。 SurfaceFlinger服务的UI渲染线程从SurfaceFlinger类的成员变量mEventQueue所描述的一个消息队列的成员函数waitMessage返回来时,假如有新的消息需要处理,那么变量msg就指向这个需要处理的新消息,即变量msg的值不等于0。目前SurfaceFlinger服务的UI渲染线程只处理一种类型为MessageQueue:INVALIDATE的消息,因此,变量msg

29、所指向的消息的类型为MessageQueue:INVALIDATE时,SurfaceFlinger服务的UI渲染线程就会从SurfaceFlinger类的成员函数waitForEvent中返回到调用它的成员函数threadLoop中去,以便可以处理把握台大事或者渲染UI的操作。 留意,当SurfaceFlinger服务的UI渲染线程从SurfaceFlinger类的成员变量mEventQueue所描述的一个消息队列的成员函数waitMessage返回来时,假如这时候显示屏仍旧处于冻结状态,那么SurfaceFlinger类的成员函数waitForEvent就需要检查显示屏的冻结时间是否已经大于

30、等于5000毫秒。假如大于等于的话,那么就会自动对显示屏执行解冻操作,即分别将SurfaceFlinger类的成员变量mFreezeDisplayTime、mFreezeCount和mFreezeDisplay的值重置为0、0和false。 SurfaceFlinger类的成员变量mEventQueue所描述的一个消息队列的类型为MessageQueue,实现在文件frameworks/base/services/surfaceflinger/MessageQueue.cpp,它与 的实现思路是类似的,不过会更简洁一些。简洁来说,这个消息队列就是由一个消息列表以及一个条件变量组成。当消息列表为

31、空时,调用MessageQueue类的成员函数waitMessage的线程就会在MessageQueue类内部的条件变量上进入睡眠等状态。而当其它线程向这个消息队列添加一个新消息的时候,就会通过MessageQueue类内部的条件变量来将前面正在等待的线程唤醒起来,以它可以将前面加入到它的消息队列中的新消息取出来处理。 至此,我们就分析完成SurfaceFlinger服务的UI渲染线程的运行模型了,在下一篇文章中我们还会连续具体分析这个线程是如何执行UI渲染操作的,接下来我们接着分析Binder线程与UI渲染线程的交互过程。 2. Binder线程与UI渲染线程的交互过程 前面提到,Syste

32、m进程在启动SurfaceFlinger服务之前,首先会启动一个Binder线程池。Binder线程池的启动过程可以参考 一文。System进程中的Binder线程池启动起来之后,其它进程,例如Android应用程序进程,就可以恳求SurfaceFlinger服务来渲染系统的UI了。 以 为例,当它需要刷新自己的UI时,就会通过它所运行在的进程的SurfaceClient单例的成员函数signalServer来向SurfaceFlinger服务发送一个Binder进程间通信恳求,这一点可以参考 一文。接下来,我们就从SurfaceClient类的成员函数signalServer来分析Surfa

33、ceFlinger服务的Binder线程与UI渲染线程的交互过程。 SurfaceClient类的成员函数signalServer的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片class SurfaceClient : public Singleton<SurfaceClient> / all these attributes are constants sp<ISurfaceComposer> mComposerService; . public: . void signalServer() const mCompose

34、rService->signal(); ; 这个函数定义在文件frameworks/base/libs/surfaceflinger_client/Surface.cpp中。 SurfaceClient类的成员变量mComposerService指向的是一个类型为BpSurfaceComposer的Binder代理对象,这个Binder代理对象引用了SurfaceFlinger服务,因此,SurfaceClient类的成员函数signalServer实际上就是通过BpSurfaceComposer类的成员函数signal来向SurfaceFlinger服务发送一个进程间通信恳求。 BpS

35、urfaceComposer类的成员函数signal的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片class BpSurfaceComposer : public BpInterface<ISurfaceComposer> public: . virtual void signal() const Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer:getInterfaceDescriptor(); remote()->transact(BnSurfaceC

36、omposer:SIGNAL, data, &reply, IBinder:FLAG_ONEWAY); ; 这个函数定义在文件frameworks/base/libs/surfaceflinger_client/ISurfaceComposer.cpp中。 从这里就可以看出,BpSurfaceComposer类的成员函数signal所执行的操作就是向SurfaceFlinger服务发送一个类型为BnSurfaceComposer:SIGNAL的进程间通信恳求,而SurfaceFlinger服务是在SurfaceFlinger类的成员函数signal中处理类型为BnSurfaceComp

37、oser:SIGNAL的进程间通信恳求的,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片void SurfaceFlinger:signal() const / this is the IPC call const_cast<SurfaceFlinger*>(this)->signalEvent(); 这个函数定义在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。 SurfaceFlinger类的成员函数signal调用了另外一个成员函数signalEvent

38、来进一步处理类型为BnSurfaceComposer:SIGNAL的进程间通信恳求的,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片void SurfaceFlinger:signalEvent() mEventQueue.invalidate(); 这个函数定义在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。 前面提到,SurfaceFlinger类的成员变量mEventQueue指向的是SurfaceFlinger服务的UI渲染线程的消息队列,这个消息队列的类型为Mess

39、ageQueue。SurfaceFlinger类的成员函数signalEvent要执行的操作便是向SurfaceFlinger服务的UI渲染线程的消息队列发送一个类型为MessageQueue:INVALIDATE的消息,这是通过调用MessageQueue类的成员函数invalidate来实现的,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片status_t MessageQueue:invalidate() Mutex:Autolock _l(mLock); mInvalidate = true; mCondition.signal(); retu

40、rn NO_ERROR; 这个函数定义在文件frameworks/base/services/surfaceflinger/MessageQueue.cpp中。 MessageQueue类的成员函数invalidate并不是真的向SurfaceFlinger服务的UI渲染线程的消息队列发送一个消息,而是将MessageQueue的类成员变量mInvalidate的值设置为true,并且通过MessageQueue类的成员变量mCondition所描述的一个条件变量来将SurfaceFlinger服务的UI渲染线程唤醒。当SurfaceFlinger服务的UI渲染线程被唤醒时,就会检查Messa

41、geQueue的类成员变量mInvalidate是否为true。假如是的话,那么就会获得一个类型为MessageQueue:INVALIDATE的消息,这个消息最终是在SurfaceFlinger类的成员函数threadLoop中处理的,如前面第1部分的内容所示。 至此,我们就分析完成SurfaceFlinger服务的Binder线程与UI渲染线程的交互过程了,接下来我们再分析SurfaceFlinger服务的把握台大事监控线程与UI渲染线程的交互过程。 3. 把握台大事监控线程与UI渲染线程的交互过程 从前面 一文可以知道,SurfaceFlinger服务的把握台大事监控线程是以Displa

42、yEventThread类的成员函数threadLoop为执行体的,即SurfaceFlinger服务的把握台大事监控线程会不断地循环调用DisplayEventThread类的成员函数threadLoop,以便可以监控硬件帧缓冲区的睡眠/唤醒状态切换大事。 DisplayEventThread类的成员函数threadLoop的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片bool DisplayHardwareBase:DisplayEventThread:threadLoop() int err = 0; char buf; int fd; f

43、d = open(kSleepFileName, O_RDONLY, 0); do err = read(fd, &buf, 1); while (err < 0 && errno = EINTR); close(fd); LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno); if (err >= 0) sp<SurfaceFlinger> flinger = mFmote(); LOGD("Abou

44、t to give-up screen, flinger = %p", flinger.get(); if (flinger != 0) mBarrier.close(); flinger->screenReleased(0); mBarrier.wait(); fd = open(kWakeFileName, O_RDONLY, 0); do err = read(fd, &buf, 1); while (err < 0 && errno = EINTR); close(fd); LOGW_IF(err<0, "ANDROID_W

45、AIT_FOR_FB_WAKE failed (%s)", strerror(errno); if (err >= 0) sp<SurfaceFlinger> flinger = mFmote(); LOGD("Screen about to return, flinger = %p", flinger.get(); if (flinger != 0) flinger->screenAcquired(0); return true; 这个函数定义在文件frameworks/base/services/surfacefli

46、nger/DisplayHardware/DisplayHardwareBase.cpp中。 从前面 一文可以知道,DisplayEventThread类的成员变量kSleepFileName要么指向文件/sys/power/wait_for_fb_sleep,要么是指向文件/sys/android_power/wait_for_fb_sleep,而DisplayEventThread类的成员变量kWakeFileName要么指向文件/sys/power/wait_for_fb_wake,要么指向文件/sys/android_power/wait_for_fb_wake。 文件/sys/pow

47、er/wait_for_fb_sleep和文件/sys/android_power/wait_for_fb_sleep是用来监控硬件帧缓冲区的睡眠大事的,而文件/sys/power/wait_for_fb_wake和文件/sys/android_power/wait_for_fb_wake是用来监控硬件帧缓冲区的唤醒大事的。文件/sys/power/wait_for_fb_sleep和文件/sys/power/wait_for_fb_wake是硬件帧缓冲区把握台供应的新式接口,而文件/sys/android_power/wait_for_fb_sleep和文件/sys/android_powe

48、r/wait_for_fb_wake是件帧缓冲区把握台供应的旧式接口。 DisplayEventThread类的成员函数threadLoop首先是监控硬件帧缓冲区的睡眠大事,这是通过监控文件kSleepFileName的内容来实现的,即首先调用函数open来打开文件kSleepFileName,然后再调用函数read来检查这个文件是否有内容可读。当文件kSleepFileName有新的内容可读时,那么就说明硬件帧缓冲区要进入睡眠状态了,这时候SurfaceFlinger服务的把握台大事监控线程就需要通知UI渲染线程来释放系统的显示屏。 DisplayEventThread类的成员变量mFlin

49、ger指向了系统中的SurfaceFlinger服务,因此,DisplayEventThread类的成员函数threadLoop就可以调用它的成员函数screenReleased来通知SurfaceFlinger服务的UI渲染线程来释放系统的显示屏。由于DisplayEventThread类的成员变量mFlinger是一个类型为SurfaceFlinger的弱指针,因此,在使用它之前,首先要调用它的成员函数promote来将它升级为一个强指针flinger。假如升级成功,那么才说明它所指向的SurfaceFlinger服务还活着。弱指针升级为强指针的原理可以参考前面 一文。 SurfaceFl

50、inger服务的把握台大事监控线程调用SurfaceFlinger类的成员函数screenReleased来通知UI渲染线程来释放系统的显示屏之后,就会通过DisplayEventThread类的成员变量mBarrier所描述的一个屏障的成员函数wait来进入到睡眠等待状态,直到被SurfaceFlinger服务的UI渲染线程唤醒为止。接下来,我们就通过SurfaceFlinger类的成员函数screenReleased来分析SurfaceFlinger服务的UI渲染线程是如何释放系统的显示屏以及唤醒把握台大事监控线程的。 SurfaceFlinger类的成员函数screenReleased的

51、实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片void SurfaceFlinger:screenReleased(int dpy) / this may be called by a signal handler, we can't do too much in here android_atomic_or(eConsoleReleased, &mConsoleSignals); Event(); 这个函数定义在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。 SurfaceFlinger类的成员函数screenReleased的实现很简洁,它首先将SurfaceFlinger类的成员变量mConsoleSignals的eConsoleReleased位设置为1,接着再通过SurfaceFlinger类的成员函数signalEvent来唤醒UI渲染线程。从前面第1部分的内容可知道,UI渲染线程被唤醒之后,就会调用SurfaceFlinger类的成员函数handleConsoleEvents来处理硬件帧缓冲区的睡眠

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论