Android SurfaceFligner Vsync信号 Jni/C++调用实现

来源:互联网 发布:2014matlab中对角矩阵 编辑:程序博客网 时间:2024/06/05 20:09

   在Anroid Vsync信号是用来通知APP进行渲染的,分为两种硬件Vsync和软件Vsync信号。我们这边不做详细介绍,这边是如何通过C++去拿到Vsync信号

   首先来看上层提供的操作接口



#include "LibLoader.h"#include <dlfcn.h>LibLoader::LibLoader() {// TODO Auto-generated constructor stubhandle = dlopen("/system/lib/libshaozhongqi.so", RTLD_NOW | RTLD_LOCAL);    if (!handle) {        //LOGE("open depend lib failed");        handle = NULL;    }}LibLoader::~LibLoader() {// TODO Auto-generated destructor stubif( handle ){dlclose(handle);}handle = NULL;}



 

#include "VSync.h"#include <dlfcn.h>//http://blog.csdn.net/smfwuxiao/article/details/6591927int VSync::init(void* h){    handle = h;    vsync_init = (__hwvsync_init)dlsym(handle,"_Z12hwvsync_initv");    hwsync= (__hwvsync)dlsym(handle, "_Z8hw_vsyncv");    hwcdeint = (__hwvsync_deinit)dlsym(handle, "_Z12vsync_Deinitv");if (!vsync_init || !hwsync || !hwcdeint ){//LOGE("dlsym fail ===== %s", dlerror());return -1;}else{isRun = true;int res = vsync_init();//LOGI("vsync init comp: %d", res);return res;}}uint64_t VSync::getVSync(){if( !isRun ){return 0;}return hwsync();}void VSync::quit(){//int res = vsync_Deinit();isRun = false;if( handle != NULL ){hwcdeint();}}

  这三个接口需要我来实现

  看一下我实现的代码:

  

/** Created By Zhongqi.Shao On 2017-09-25*/#pragma once#include <gui/BitTube.h>#include <gui/ISurfaceComposer.h>#include <gui/Surface.h>#include <gui/SurfaceComposerClient.h>#include <private/gui/ComposerService.h>#include <gui/DisplayEventReceiver.h>#include <utils/Looper.h>#include <pthread.h>#include "EventQueue.h"#define RUN 1#define STOP 0using namespace android;namespace nvr{  class VsyncClient{  private:    //sp<ISurfaceComposer> surfaceFligner;//sp<DisplayEventReceiver> mSpEventReceiver;VsyncClient();static VsyncClient * pInstance = NULL;int status = STOP;public:   DisplayEventReceiver* mDisplayEvent;    //sp<BitTube> mChannel;Looper* mloop;pthread_t* mPollThred; EventQueue* mEventQueue;Event* tempEvent;pthread_mutex_t* eventMutex;pthread_cond_t*notEmpty;pthread_mutex_t* threadMutex;pthread_cond_t*threadStatus;virtual ~VsyncClient();static void * StartePoll( void * parm );void runThread();void startPollThread();void thread_resume();void thread_pause();    int initClient();int initEnv();uint64_t getVsync();void stopClient();static VsyncClient* GetInstance(){    if(pInstance == NULL){  pInstance = new VsyncClient();}    return pInstance;}};}

  

#include <vsync/VsyncClient.h>#include <gui/DisplayEventReceiver.h>#include <utils/Errors.h>#define ALOOPER_EVENT_INPUT              1 << 0using namespace android;namespace nvr{VsyncClient::VsyncClient(){int envStatus = initEnv();}VsyncClient::~VsyncClient(){ ALOGD("vsyncpp happened wrong this object cannot release!!!");}void *VsyncClient::StartePoll( void * parm ){VsyncClient & client = *(VsyncClient *)parm;client.runThread();return NULL;}int VsyncClient::initClient(){thread_resume();mDisplayEvent->setVsyncRate(1);    return 0;}int receiver(int fd, int events, void* data){VsyncClient* client = (VsyncClient*)data;    DisplayEventReceiver* q = client->mDisplayEvent;if(q == NULL){  ALOGD("vsyncpp receiver event = null");  return 0;}//EventQueue* eventQueue = client->mEventQueue;    ssize_t n;    DisplayEventReceiver::Event buffer[1];    static nsecs_t oldTimeStamp = 0;    while ((n = q->getEvents(buffer, 1)) > 0) {        for (int i=0 ; i<n ; i++) {            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {                            }pthread_mutex_lock(client->eventMutex);/*锁住互斥量*/  client->tempEvent->timestamp = buffer[i].header.timestamp;pthread_cond_signal(client->notEmpty);/*条件改变,发送信号,通知t_b进程*/     pthread_mutex_unlock(client->eventMutex);/*解锁互斥量*///ALOGD("shao1 event vsync: time=%lld\t",client->tempEvent->timestamp);        }    }    if (n<0) {        ALOGD("vsyncpp error reading events (%s)\n", strerror(-n));    }    return 1;}void VsyncClient::runThread(){do {    pthread_mutex_lock(threadMutex);        while (!status)        {            pthread_cond_wait(threadStatus, threadMutex);        }        pthread_mutex_unlock(threadMutex);        int32_t ret = mloop->pollOnce(-1);    } while (1);}void VsyncClient::startPollThread(){pthread_attr_t attr;pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);struct sched_paramstShedParam;pthread_attr_getschedparam(&attr, &stShedParam);    pthread_attr_setschedpolicy(&attr, SCHED_FIFO);    stShedParam.sched_priority = 90;    pthread_attr_setschedparam(&attr, &stShedParam);const int createErr = pthread_create(mPollThred, &attr ,&StartePoll, this ); pthread_attr_destroy(&attr);if ( createErr != 0 ){ALOGE("============= os create vsync thread failed");}else{ALOGD("============= os create vsync thread succ");}}void VsyncClient::thread_resume(){if (status == STOP){           pthread_mutex_lock(threadMutex);        status = RUN;        pthread_cond_signal(threadStatus);       ALOGD("vsyncpp thread run\n");        pthread_mutex_unlock(threadMutex);    }       else{          ALOGD("vsyncpp thread has already run");    }   }void VsyncClient::thread_pause(){if (status == RUN){           pthread_mutex_lock(threadMutex);        status = STOP;        ALOGD("vsyncpp thread stop\n");        pthread_mutex_unlock(threadMutex);    }       else{            ALOGD("vsyncpp thread has alreay stop\n");    }}int VsyncClient::initEnv(){    tempEvent = new Event();eventMutex = new pthread_mutex_t();notEmpty = new pthread_cond_t();threadMutex = new pthread_mutex_t();threadStatus = new pthread_cond_t();    mDisplayEvent = new DisplayEventReceiver();status_t status = mDisplayEvent->initCheck();mDisplayEvent->setVsyncRate(1);    mloop = new Looper(false);    mloop->addFd(mDisplayEvent->getFd(), 0, ALOOPER_EVENT_INPUT, receiver,this);mPollThred = new pthread_t();pthread_mutex_init(eventMutex, NULL /* default attributes */ );pthread_cond_init(notEmpty, NULL /* default attributes */ );pthread_mutex_init(threadMutex, NULL /* default attributes */ );pthread_cond_init(threadStatus, NULL /* default attributes */ );    startPollThread();return 0;}uint64_t VsyncClient::getVsync(){    pthread_mutex_lock(eventMutex);/*锁住互斥量*/pthread_cond_wait(notEmpty,eventMutex);/*解锁mutex,并等待cond改变*/  Event tEvent;tEvent.timestamp = tempEvent->timestamp;pthread_mutex_unlock(eventMutex);ALOGD("shao2 event vsync: time=%lld\t",tEvent.timestamp);return tEvent.timestamp;}void VsyncClient::stopClient(){thread_pause();mDisplayEvent->setVsyncRate(0);    }}


主要逻辑如下:

1:单例情况下在构造函数里面创建DisplayEventReceiver对象

     看一下DisplayEventReceiver构造里面做了什么操作

    

DisplayEventReceiver::DisplayEventReceiver() {    sp<ISurfaceComposer> sf(ComposerService::getComposerService());    if (sf != NULL) {        mEventConnection = sf->createDisplayEventConnection();        if (mEventConnection != NULL) {            mDataChannel = mEventConnection->getDataChannel();        }    }}DisplayEventReceiver::~DisplayEventReceiver() {}status_t DisplayEventReceiver::initCheck() const {    if (mDataChannel != NULL)        return NO_ERROR;    return NO_INIT;}int DisplayEventReceiver::getFd() const {    if (mDataChannel == NULL)        return NO_INIT;    return mDataChannel->getFd();}status_t DisplayEventReceiver::setVsyncRate(uint32_t count) {    if (int32_t(count) < 0)        return BAD_VALUE;    if (mEventConnection != NULL) {        mEventConnection->setVsyncRate(count);        return NO_ERROR;    }    return NO_INIT;}status_t DisplayEventReceiver::requestNextVsync() {    if (mEventConnection != NULL) {        mEventConnection->requestNextVsync();        return NO_ERROR;    }    return NO_INIT;}

 sp<ISurfaceComposer> sf(ComposerService::getComposerService());拿到surfacefligner service binder对象,mEventConnection = sf->createDisplayEventConnection();创建connection对象,这个mEventConnectio到底是什么?本质就是包含BitTube管道用来实现进程通信的类



2:添加

 mloop->addFd(mDisplayEvent->getFd(), 0, ALOOPER_EVENT_INPUT, receiver,this);实现对管道的监听,有数据写入管道就会调用receiver这个函数,我在这个函数里面将最新数据写入tempEvent这个Object


3:开启线程不停调用pollonce()才能促发receiver回调,然后采用生产者消费者模式将数据返回给getVsync()接口


到此流程结束




原创粉丝点击