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()接口
到此流程结束
阅读全文
1 0
- Android SurfaceFligner Vsync信号 Jni/C++调用实现
- VSync信号
- android studio 调用jni,实现Java调用C语言程序
- Android VSync信号产生过程源码分析
- android调用本地C/C++代码,jni的实现
- android j使用JNI实现ava语言调用C语言
- android实现app通过jni调用C/C++方法
- Android利用JNI实现java调用C或C++
- android实现app通过jni调用C/C++方法
- Android Cmake 编译c,c++源文件,实现JNI调用
- Android NDK编译c,c++源文件,实现JNI调用
- Android底层调用C代码(JNI实现)
- android JNI调用C/C++
- android jni调用c库
- Android JNI 调用 C/C++
- Android JNI 调用 C/C++
- Android JNI C调用Java
- Android JNI/NDK开发(2)JNI实现C/C++与Android/JAVA相互调用
- 20170929在stm32f103zet6 RTT上扩展外部SRAM
- iOS开发 ☞ 关于带系统导航栏坐标的问题
- 20行代码能干嘛?
- Android中建造者(builder)模式
- Redis中RDB持久化
- Android SurfaceFligner Vsync信号 Jni/C++调用实现
- OplogThread: Last entry no longer in oplog cannot recover!
- 堆排序算法的实现(HeapSort)
- 转-C++快速入门
- scrapy爬虫的暂停与重启
- 面向对象状态机框架
- 如何做到phpmyadmin中最大限制:2,048KB 解决办法
- OpenCV-将图像作平滑处理并显示
- Wait waitpid