android vsnc 工作原理

来源:互联网 发布:非农数据软件 编辑:程序博客网 时间:2024/04/30 08:46


                           

我们知道Android是用Vsync来驱动系统的画面更新包括APPview draw ,surfaceflinger 画面的合成,displaysurfaceflinger合成的画面呈现在LCD.我们将在本文探讨AndroidVsync的实现.

Vsync的构成

 

systrace,我们经常可以看到如上图的信息.

  • 红色框1是与Vsync相关event信息.这些Vsync event构成了android系统画面更新基础.

  • 红色框2和红色框3Vsync-app的信息.我们可以看到红色框2比红色框3稀疏.我们将会在本文说明其原因.

  • 红色框4和红色框5Vsync-sf的信息.我们可以看到红色框4比红色框5稀疏.我们将会在本文说明其原因.

Vsync信号

 

Vsync信号由HW_VSYNC_ON_0,HW_VSYNC_0, Vsync-appVsync-sf四部分构成.

  • HW_VSYNC_ON_0

    代表PrimaryDisplayVSyncenabledisable.0这个数字代表的是display的编号, 0PrimaryDisplay,如果是Externalmonitor,就会是HW_VSYNC_ON_1.SF要求HWComposerDisplayVSync打开或关掉时,这个event就会记录下来.

  • HW_VSYNC_0

    代表PrimaryDisplayVSync发生时间点, 0同样代表display编号.其用来调节Vsync-appVsync-sfevent的输出.

  • Vsync-app

    App,SystemUIsystemserver viewdraw的触发器.

  • Vsync-sf

    Surfaceflinger合成画面的触发器.

通常为了避免Tearing的现象,画面更新(Flip)的动作通常会在VSync开始的时候才做,因为在VSync开始到它结束前, Display不会把framebuffer资料显示在display,所以在这段时间做Flip可以避免使用者同时看到前后两个部份画面的现象.目前user看到画面呈现的过程是这样的,app更新它的画面后,它需要透过BufferQueue通知SF, SF再将更新过的app画面与其它的AppSystemUI组合后,再显示在User面前.在这个过程里,3component牵涉进来,分别是App,SF,Display.以目前AndroidM的设计,这三个Component都是在VSync发生的时候才开始做事.我们将它们想成一个有3stagepipeline,这个pipelineclockLCDTE信号(60HZ)也即HW_VSYNC_0.

 

我们来看看android drawpipeline.如下,

 


1. T = 0, App正在画N, SFDisplay都没内容可用

2. T = 1, App正在画N+1, SF组合N, DisplayBuffer可显示

3. T = 2, App正在画N+2, SF组合N+1, Display显示N

4. T = 3, App正在画N, SF组合N+2, Display显示N+1

5. ...

 

如果按照这个步骤,user改变一个画面时,要等到2VSync,画面才会显示在user面前, latency大概是33ms (2frame的时间).但是对大部份的操作来讲,可能appSF画的时间一个frame(16.6ms)就可以完成.因此, Android就从HW_VSYNC_0中产生出两个VSync信号,VSYNC-app是给App用的, VSYNC-sf是给SF用的, Display则是使用HW_VSYNC_0.VSYNC-appVSYNC-sf可以分别给定一个phase,简单的说

VSYNC-app = HW_VSYNC_0 + phase_app

VSYNC-sf =HW_VSYNC_0 + phase_sf

从而使App drawsurfaceflinger的合成,错开时间运行.这样就有可能整个系统drawpipeline更加有效率,从而提高用户体验.

 

也就是说,如果phase_appphase_sf设定的好的话,可能大部份user使用的状况, App+SF可以在一个frame里完成,然后在下一个HW_VSYNC_0来的时候,显示在display.

理论上透过VSYNC-sfVSYNC-app的确是可以有机会在一个frame里把App+SF做完,但是实际上不是一定可以在一个frame里完成.因为有可能因为CPU调度,GPUperformance不够,以致AppSF没办法及时做完.但是即便如此,app,surfaceflingerdisplayVsync分开也比用一个Vsynctrigger appdraw,surfaceflinger合成,displayLCDdraw的性能要好很多.(FPS更高).

 

那么是否我们收到LCDVsyncevent就会触发Vsync-appVsync-SF.如果是这样我们就不会看到本文开头的Vsync-appVsync-SF的节奏不一致的情况(红色框2比红色框3稀疏).事实上,在大多数情况下,APP的画面并不需要一直更新.比如我们看一篇文章,大部份时间,画面是维持一样的,如果我们在每个LCDVSYNC来的时候都触发SFAPP,就会浪费时间和Power.可是在画面持续更新的情况下,我们又需要触发SFAppVsync event.例如玩game或播影片时.就是说我们需要根据是否有内容的更新来选择Vsyncevent出现的机制.Vsync event 的触发需要按需出现.所以在Android, HW_VSYNC_0,Vsync-sfVsync-app都会按需出现. HW_VSYNC_0是根据是否需要调节sfappVsyncevent而出现,SFApp则会call requestNextVsync()来告诉系统我要在下一个VSYNC需要被trigger.也是虽然系统每秒有60HW VSYNC,但不代表APPSF在每个VSYNC都要更新画面.因此,Android,是根据SoftwareVSYNC(Vsync-sf,Vsync-app)来更新画面.Software VSYNC是根据HWVSYNC过去发生的时间,推测未来会发生的时间.因此,APPSF利用requestNextVsync,Software VSYNC才会触发VSYNC-sfVSYNC-app.

 

Vsync event的产生

 

下图是Vsyncevent产生的示意图.

这里HW_VSYNC就是HW_VSYNC_0.

SFHWComposer收到VSYNC(HW_VSYNC_0),它会利用DispSync::addResyncSample将新的VSYNC时间交给DispSync.addResyncSample决定是否还需要HW_VSYNC的输入,如果不需要,就会将HW_VSYNC关掉.

 

voidSurfaceFlinger::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);

   }

}

 

另一方面,sufaceflinge合成图片后也会check是否需要开启HW_VSYNC来调整SW_VSYNC.

 

SurfaceFlinger::postComposition(),会将PresentFence的时间通过addPresentFence交给DispSync,来检查SW_VSYNC是否需要校正,如果需要,就会将HW_VSYNC打开.

voidSurfaceFlinger::postComposition()

 {

   const LayerVector&layers(mDrawingState.layersSortedByZ);

   const size_t count = layers.size();

   for (size_t i=0 ; i<count ; i++) {

       layers[i]->onPostComposition();

   }

 

   const HWComposer& hwc =getHwComposer();

   sp<Fence> presentFence =hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);

 

   if (presentFence->isValid()) {

       if(mPrimaryDispSync.addPresentFence(presentFence)) {

           enableHardwareVsync();

       } else {

           disableHardwareVsync(false);

       }

   }

 

   const sp<const DisplayDevice>hw(getDefaultDisplayDevice());

   if (kIgnorePresentFences) {

       if (hw->isDisplayOn()) {

           enableHardwareVsync();

       }

   }

…..

}

 

DispSync是利用HW_VSYNCPresentFence来判断是否需要开启HW_VSYNC.HW_VSYNC最少要3,最多是32,实际上要用几个则不一定,DispSync拿到3HW_VSYNC后就会计算出SW_VSYNC,只要收到的PresentFence没有超过误差,HW_VSYNC就会关掉,以便节省功耗.不然会继续开启HW_VSYNC计算SW_VSYNC的值,直到误差小于threshold.其计算的方法是DispSync::updateModelLocked().

基本思想如下,

  • 计算目前收到HW_VSYNC间隔,取平均值(AvgPeriod) HW_VSYNC

  • 将每个收到的VSYNC时间与AvgPeriod算出误差. (Delta = Time %AvgPeriod)

  • Delta转换成角度(DeltaPhase),如果AvgPeriod360,DeltaPhase = 2*PI*Delta/AvgPeriod.

  • DeltaPhase可以得到DeltaXDeltaY (DeltaX =cos(DeltaPhase), DeltaY = sin(DeltaPhase))

  • 将每个收到的VSYNCDeltaXDeltaY取平均,可以得到AvgXAvgY

  • 利用atanAvgX, AvgY可以得到平圴的phase (AvgPhase)

  • AvgPeriod + AvgPhase就是SW_VSYNC.

 

DispSync收到addPresentFence(最多记录8sample),每一个fence的时间算出(Time% AvgPeriod)的平方当作误差,将所有的Fence误差加总起来如果大于某个Threshold,就表示需要校正(DispSync::updateErrorLocked).校正的方法是呼叫DispSync::beginResync()将所有的HW_VSYNC清掉,开启HW_VSYNC.等至少3HW_VSYNC再重新计算.

Vsync的代码实现

我们知道Vsyncandroiddisplay系统的重要基石,其驱动androiddisplay系统不断的更新App侧的绘画,并把相关内容及时的更新到LCD.其包含的主要代码如下:

frameworks\native\services\surfaceflinger\DispSync.cpp
frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp

frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp@DispSyncSource

frameworks\native\services\surfaceflinger\EventThread.cpp

frameworks\native\services\surfaceflinger\MessageQueue.cpp

frameworks\native\libs\gui\BitTube.cpp

frameworks\native\libs\gui\BufferQueueProducer.cpp

  • DispSync.cpp

    这个class包含了DispSyncThread.SW-SYNC的心脏.所有的SW-SYNCevent均由其产生.Android系统中,只有一个DispSync.

  • SurfaceFlinger.cpp

    这个类主要处理layer的合成.它合成好相关的layer后发送commandHWdisplay进行进行显示.

  • DispSyncSource

    Vsync source Android系统中有两个instance.一是Vsync-app.另一个Vsync-sf.SW-SYNC发生时,Vsyncsourcecallback到其相应的EventThread,并且会在Systrace上显示出Vsync-sfVsync-app的跳变.

  • EventThread.cpp

    Vsync event处理线程.在系统中有两个EventThread.一个用于Vsync-app,另一个用于Vsync-sf.其记录AppSurfaceFlingerrequestnextVsync()请求,SW-VSYNCevent触发时,EventThread线程通过BitTube通知AppSurfaceFlinger.App开始drawview,SurfaceFlinger开始合成 dirty layer.

  • MessageQueue.cpp

    MessageQueue 主要处理surfaceflingerVsync请求和发生Vsync事件给surfaceFlinger.

  • BitTube.cpp

    Vsync 事件的传输通道.AppSurfaceflinger首先与EventThread建立DisplayEventConnection(EventThread::Connection::Connection,ConnectionBnDisplayEventConnection子类,BitTube是其dataChannel).AppsurfaceFlinger通过call DisplayEventConnection::requestNextVsync()(binder 通信)EventThread请求Vsyncevent.EventThread收到SW-VSYNCevent,其通过BitTubeVsyncevnet发送给AppSufaceFlinger.

  • BufferQueueProducer.cpp

    Vsync架构中,其主要作用是向EventThread请求Vsync-sfevent.App画完一个frame,其会把画完的buffer放到bufferqueue中通过call BufferQueueProducer::queueBuffer().进而surfaceflinger进程会通过callDisplayEventConnection:: requestNextVsync()EventThread请求Vsync event.

     

Vsync流程

App需要draw一个frame,其会向EventThread(appEventThread)请求Vysncevent,EventThread收到Vsyncevent,EventThread通过BitTuebVsyncevent通知到App,同时跳变systrace中的Vsync-app.App收到Vsync-app,开始draw frame.App画完一个frame,把画好的内容放到bufferqueue,就会要求一个Vsync-sfevent,以便surfaceflinger在收到Vsync-sfevent时合成相关的dirty的内容并通知DisplayHW.Display HW 会在下一个HWvsync时间点,把相关的内容更新到LCD上完成内容的更新.

下面是其大概的流程图,

 

  1. (SF-1)APP 画完一个frame以后,就会把其绘画的buffer放到buffer queue.从生产者和消费者的关系来看,App是生产者,surfaceflinger进程是消费者.

  2. (SF-2)SurfaceFlinger 进程内,当收到有更新的可用的frame(需要renderLCD ),就会向EventThread请求Vsync event(requestNextVsync()).EventThread会记录下此请求,当下次Vsync event到来时,便会triggerVsync-sf event.

  3. DispSync 不断产生SW-VSYNCEVENT.SW-VSYNCEVENT产生时,会检查是否有EventListener关心该event(SFAPP请求Vsync时会在DispSync中创建EventListener并把其相应的DispSyncSource作为EventListenercallback),如有则调用EventListenercallback(DispSyncSource)onDispSyncEvent.(callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime)).

  4. DispSyncSource会引起Vsync-sfVsync-app跳变,onDispSyncEvent()被调用时,并且会直接调用EventThreadonVSyncEvent().

  5. EventThread会把Vsync-sfVsync-app event通知到AppsurfaceFlingerVsync-sfevent产生时(callonDispSyncEvent),surfaceflinger进程合成dirty layer的内容(SF-5)并通知Display HW把相关的更新到LCD.App则在Vsync-ap时开始drawview.

  6. Display HW 便会在HWvsync 到来时,更新LCD 的内容(SF-6).

  7. 如果有Layer 的内容需要更新,surfaceflinger 便会把相关内容合成在一起,并且通知DisplayHW ,有相关的更新内容.

我们来看看其代码的实现.

void SurfaceFlinger::init()

{

   

   // start the EventThread

   sp<VSyncSource>vsyncSrc = new DispSyncSource(&mPrimaryDispSync,

           vsyncPhaseOffsetNs, true,"app");

   mEventThread = newEventThread(vsyncSrc);

   sp<VSyncSource>sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,

           sfVsyncPhaseOffsetNs, true, "sf");

   mSFEventThread= new EventThread(sfVsyncSrc);

   mEventQueue.setEventThread(mSFEventThread);

}

surfaceFlinger初始化时,其创建了两个DispSyncSource和两个EventThread.一个用于APP,而另一个用于SurfaceFlinger本身.我们知道DispSyncSourceDispSync协同工作,共同完成Vsynceventfire.EventThreadtriggerApp draw framesurfaceFlinger合成”dirty”layerSW-VSYNCevent产生时.

我们在这里列出DispSyncSourceVsync-sf有关系的code.

class DispSyncSource : publicVSyncSource, private DispSync::Callback {

public:

   DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,

   

   virtual void setVSyncEnabled(bool enable) {

       Mutex::Autolock lock(mVsyncMutex);

       if (enable) {

           status_t err =mDispSync->addEventListener(mPhaseOffset,

                   static_cast<DispSync::Callback*>(this));

….

       } else {

           status_t err = mDispSync->removeEventListener(

                   static_cast<DispSync::Callback*>(this));

….

           }

   virtual void onDispSyncEvent(nsecs_t when) {

       sp<VSyncSource::Callback> callback;

       {

           Mutex::Autolocklock(mCallbackMutex);

           callback = mCallback;

 

           if (mTraceVsync) {

               mValue = (mValue + 1) % 2;

               ATRACE_INT(mVsyncEventLabel.string(), mValue);

           }

       }

       if (callback != NULL) {

           callback->onVSyncEvent(when);

       }

}

….

}

其中最重要的两个functionsetVSyncEnabled(bool enable)onDispSyncEvent(nsecs_twhen). setVSyncEnabled()的功能是把自己注册到DispSync(enable=true)中或者从DispSyncremove掉自己(enale=false),DispSync产生了SW-VSYNCevent,checkSW-VSYNC感兴趣的DispSyncSource并回调其onDispSyncEvent().onDispSyncEvent()主要的功能一是enableVsync-sfsytrace,一是callback EventThread中的onVSyncEvent(),从而触发SurfaceFlinger合成所有更新的layer.

下面我们来看看EventThread的重要code

EventThread::Connection::Connection(

       constsp<EventThread>& eventThread)

   : count(-1),mEventThread(eventThread), mChannel(new BitTube())

{

}

sp<EventThread::Connection>EventThread::createEventConnection()const {

   return new Connection(const_cast<EventThread*>(this));

}

status_tEventThread::registerDisplayEventConnection(

       constsp<EventThread::Connection>& connection) {

   Mutex::Autolock _l(mLock);

   mDisplayEventConnections.add(connection);

   

}

 

voidEventThread::requestNextVsync(

   if (connection->count < 0) {

       connection->count = 0;

       mCondition.broadcast();

   }

}

 

void EventThread::onVSyncEvent(nsecs_t timestamp){

   Mutex::Autolock _l(mLock);

   mCondition.broadcast();

}

 

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 reportthis event

       status_t err = conn->postEvent(event);

}

// This will return when (1) avsync event has been received, and (2) there was

// at least one connectioninterested in receiving it when we started waiting.

Vector<sp<EventThread::Connection> >EventThread::waitForEvent(

       DisplayEventReceiver::Event* event)

{

   Mutex::Autolock _l(mLock);

   Vector< sp<EventThread::Connection> > signalConnections;

do {

….

       // find out connections waiting forevents

       size_t count =mDisplayEventConnections.size();

       for (size_t i=0 ; i<count ; i++) {

     ….

               if (connection->count >= 0) {

                   // we need vsync eventsbecause at least

                   // one connection iswaiting for it

                   waitForVSync = true;

                   if (timestamp) {

                       if(connection->count == 0) {

                           // fired this timearound

                           connection->count = -1;

                           signalConnections.add(connection);

}

       // Here we figure out if we need toenable or disable vsyncs

       if (timestamp && !waitForVSync){

           // we received a VSYNC but we haveno clients

           // don't report it, and disableVSYNC events

           disableVSyncLocked();

       } else if (!timestamp &&waitForVSync) {

           // we have at least one client, sowe want vsync enabled

           // (TODO: this function is calledright after we finish

           // notifying clients of a vsync, sothis call will be made

           // at the vsync rate, e.g.60fps. If we can accurately

           // track the current state we couldavoid making this call

           // so often.)

           enableVSyncLocked();

       }

       if (!timestamp &&!eventPending) {

           // wait for something to happen

           if (waitForVSync) {

               

               if (mCondition.waitRelative(mLock, timeout) ==TIMED_OUT) {

                   …..

               }

           } else {

               // Nobody is interested invsync, so we just want to sleep.

               mCondition.wait(mLock);

           }

       }

   } while (signalConnections.isEmpty());

   return signalConnections;

}

我们列出了EventThread的重要function.下面一一说明其功能.

  • EventThread::Connection::Connection()

    Connection的构造函数.用于进程间的通信by BitTube..在此处主要是搭建一个通路(BitTube)来完成client(AppSurfaceFlinger)Vsyncevent事件的请求(通过requestNextVsync())EventThreadSW-Vsyncevent callback到其感兴趣的client.需要注意的是App是通过SurfaceFlinger::createDisplayEventConnection()创建此连接的.sufaceflinge是在其初始化时callEventQueue.setEventThread(mSFEventThread)创建的.所以对App EventThread 来说可能有多个connection ,也有可能没有.而对sufaceflinger目前来说有且只有一个.

  • sp<EventThread::Connection>EventThread::createEventConnection()

    创建 Connection连接.

  • status_tEventThread::registerDisplayEventConnection()

    如其名所描述.其功能是把创建的Connection注册到一个容器中.SW-VSYNCevent发生时,EventThread会从Connection注册的容器中,找到那些对SW-VSYNCevent感兴趣的connection并把vsyncevent通过BitTube传到client.

  • void EventThread::requestNextVsync()

    Clinet 端通过Connectioncall 这函数通知EventThread,其对SW-SYNCevent的请求.

  •  voidEventThread::onVSyncEvent(nsecs_t timestamp)

    SW-VSYNCEVENT 发生时,DispSyncSource call此函数,告知EventThread,Vsyncevent已经发生,如果此时有connectVsync感兴趣,EventThread便会通过connect->postEvent(event)Vsync事件发送到client(Appsurfaceflinger).

  • bool EventThread::threadLoop()

    线程的主体函数.其完成两件事.一是把对SW-VSYNCevent有请求并且还没有处理的connect找出来.而是把Vsyncevent通过connect通知到client.

  • Vector< sp<EventThread::Connection>> EventThread::waitForEvent()

    EventThread 的主要功能都在此函数里.此函数由threadLoop()调用.EventThread在大部分时间里是sleep.如果系统的性能比较好,那么其sleep的节奏是和SW-VSYNCevent的节奏一致.16.6mssleep一次.然而由于其Appsurfaceflinger没有Vsync的请求,sleep的时间为更长.此函数的名为waitForEvent,其到底在等什么event?原来此函数在等待的event就是Dispsync产生的SW-SYNCevent.其功能check所有的connect是否有Vsync事件请求根据不同的情况做如下处理.

  1. 所有的connect都没有Vsync请求,则其通过disableVSyncLocked(),disableVsync event,那么此EventThread将不会收到SW-SYNCevent,一直sleep直到有connectVsync请求为止.

  2. 在所有的connect,SW-SYNC event请求,但是当其请求SW-SYNCevent,SW-SYNCevent还没有fire,则其通过enableVSyncLocked()enable Vsync并进入sleep.当下一个SW-SYNCevent来到时,便把所有有SW-SYNCevent请求的connection返回给threadLoop.

下图是big pic.

 

Vsync-app实例

本图是一个非常典型的Androiddisplay系统如何利用Vsync-appevent来更新Appview.

  1. App 通过ConnectionEventThread请求SW-VSYNCevent(最终并且通过callEventThread::requestNextVsync()).一般来说App是通过Choreographer.doScheduleVsync()来请求Vsyncevent.

  2. DispSync 产生SW-VSYNC eventcall DispSyncSourceonDispSyncEvent().

  3. DispSyncSource产生VSYNC-app信号跳变.

  4. 同时DispSyncSource使EventThread(app)waitForEvent()结束sleep,并把VSYNC-app通知到App进程(gallery3d).

  5. Gallery3d 进程收到VSYNC-app信号,在其main线程(UI Thread)中开始draw一个frame(发送draw commandGL thread).

  6. GL Thread 开始draw view.

  7. GL thread 线程Draw 完一frame,draw buffer放到buffer queue.

  8. SufaceView中画好的buffer 数据增加为1.这个buffer 将被surfaceflinger 在适当的时候合成.

     

Vsync-sf实例

 

上图是一个典型的Vsync-sf的实例.

  1. App draw 完一个frame (SurfaceView) 并且把此frame通过调用BufferQueueProducer::queueBuffer()放到bufferqueue,并且通过call EventThread::requestNextVsync(),请求SW-VSYNCevent.此时由于DispSync没有fireSW-Sync event所以EventThreadEventThread::waitForEvent()sleep.

  2. DispSync触发SW-SYNC event信号并且call DispSyncSource::onDispSyncEvent().

  3. DispSyncSource::onDispSyncEvent()中首先引起Vsync-sf跳变,然后在call EventThread::onVSyncEvent(nsecs_ttimestamp).

  4. EventThread::onVSyncEvent(nsecs_ttimestamp),会唤醒EventThread::waitForEvent()中的sleep,从而发送消息到Surfaceflinger.

  5. SurfaceFlinger收到EventThread发过来的Vsync-sf跳变信息,开始合成dirty layer,本例是SurfaceView.合成完以后发送更新的消息到DisplayHW.

  6. Display HW 收到更新的消息时,HW vsync event还没有来,因此DisplayHW sleep了一段事件.HWvsync event到来时,DisplayHW 便更新其LCD的内容.把最新的内容显示在LCD.

自此我们完成了Vsync子系统的分析.回到系统性能上,我们可以看出系统的性能(FPS)可能于如下因素有关.

  1. DispSync的调度. DispSyncVsync系统的心脏,如果DispSync来不及调度,则有可能由于去SW-SYNC event的产生不及时而影响系统的性能.

  2. View Draw 花费了过多的时间也会引性能问题, 如果其不能在一个SW-SYNC时间内完成, 那么此应用就会有一个Janks.由于现在的Androd系统都采用了HWUI,viewdraw往往是GPU直接draw,所以很多时候是GPUperformance问题.

  3. HW display 的性能问题.LCD 上所绘画的内容, 最终需要HW displayHW vsync触发是把其内容显示在LCD.

  4. Binder 的调度问题, 我们可以看到无论是requestNextVsync () 还是queueBuffer()都是App通过bindersurfaceflinger进程通信的.而这些binder在大多数时间是sleep.如果binder由于CPU调度而错过了一个Vsync跳变点,那么就有一个frame发生Janks.

0 0