如何在android framework裡建立執行緒Thread
阿新 • • 發佈:2018-12-09
android 執行緒Thread介紹:
https://blog.csdn.net/qq_33670826/article/details/81483520
下面在安卓display裡建立執行緒為例:
diff --git a/display/display/DisplayManager.cpp b/display/display/DisplayManager.cpp index 07cb1be..f671326 100644 --- a/display/display/DisplayManager.cpp +++ b/display/display/DisplayManager.cpp @@ -18,6 +18,8 @@ #include <dirent.h> #include <cutils/log.h> #include <cutils/properties.h> +#include <sys/epoll.h> +#include <sys/inotify.h> #include "FbDisplay.h" #include "KmsDisplay.h" @@ -65,6 +67,10 @@ DisplayManager::DisplayManager() mDrmMode = false; mDriverReady = true; enumKmsDisplays(); + if (!mDriverReady) { + mPollFileThread = new PollFileThread(this); + } + if (!mDrmMode) { enumFbDisplays(); } @@ -91,6 +97,9 @@ DisplayManager::~DisplayManager() if (mHotplugThread != NULL) { mHotplugThread->requestExit(); } + if (mPollFileThread != NULL) { + mPollFileThread->requestExit(); + } Display* display = getPhysicalDisplay(DISPLAY_PRIMARY); display->setVsyncEnabled(false); @@ -210,6 +219,12 @@ void DisplayManager::setCallback(EventListener* callback) display->setCallback(callback); } +EventListener* DisplayManager::getCallback() +{ + Mutex::Autolock _l(mLock); + return mListener; +} + bool DisplayManager::isOverlay(int fb) { char fb_path[HWC_PATH_LENGTH]; @@ -512,13 +527,6 @@ void DisplayManager::handleKmsHotplug() callback = mListener; } - if (!mDriverReady) { - enumKmsDisplays(); - if (callback != NULL) { - callback->onRefresh(i); - } - } - bool connected = display->connected(); display->readConnection(); if (display->connected() == connected) { @@ -602,4 +610,98 @@ bool DisplayManager::HotplugThread::threadLoop() return true; } +DisplayManager::PollFileThread::PollFileThread(DisplayManager *ctx) + : Thread(false), mCtx(ctx), mINotifyFd(-1), mINotifyWd(-1), mEpollFd(-1) +{ +} + +void DisplayManager::PollFileThread::onFirstRef() +{ + run("HWC-Poll-Thread", android::PRIORITY_URGENT_DISPLAY); +} + +int32_t DisplayManager::PollFileThread::readyToRun() +{ + mINotifyFd = inotify_init(); + if (mINotifyFd < 0) { + ALOGE("Fail to initialize inotify fd, error:%s",strerror(errno)); + return -1; + } + + mINotifyWd = inotify_add_watch(mINotifyFd, DRM_DRI_PATH, IN_CREATE); + if (mINotifyWd < 0) { + ALOGE("Fail to add watch for %s,error:%s",DRM_DRI_PATH,strerror(errno)); + close(mINotifyFd); + return -1; + } + + mEpollFd = epoll_create(1); + if (mEpollFd == -1) { + ALOGE("Fail to create epoll instance, error:%s",strerror(errno)); + inotify_rm_watch(mINotifyFd,mINotifyWd); + close(mINotifyFd); + return -1; + } + epoll_event eventItem; + memset(&eventItem, 0, sizeof(epoll_event)); + eventItem.events = EPOLLIN; + eventItem.data.fd = mINotifyFd; + int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem); + if (result == -1) { + ALOGE("Fail to add inotify to epoll instance, error:%s",strerror(errno)); + inotify_rm_watch(mINotifyFd,mINotifyWd); + close(mINotifyFd); + close(mEpollFd); + return -1; + } + return 0; +} + +bool DisplayManager::PollFileThread::threadLoop() +{ + int numEpollEvent = 0; + epoll_event epollItems[EPOLL_MAX_EVENTS]; + numEpollEvent = epoll_wait(mEpollFd, epollItems, EPOLL_MAX_EVENTS, -1); + if (numEpollEvent <= 0) { + ALOGE("Fail to wait requested events,numEpollEvent:%d,error:%s",numEpollEvent,strerror(errno)); + return true; + } + + for (int i=0; i<numEpollEvent; i++) { + if (epollItems[i].events & (EPOLLERR|EPOLLHUP)) { + continue; + } + if (epollItems[i].events & EPOLLIN) { + char buf[BUFFER_SIZE]; + int numINotifyItem = read(mINotifyFd,buf,BUFFER_SIZE); + if (numINotifyItem < 0) { + ALOGE("Fail to read from INotifyFd,error:%s",strerror(errno)); + continue; + } + + //Each successful read returns a buffer containing one or more of struct inotify_event + //The length of each inotify_event structure is sizeof(struct inotify_event)+len. + for (char *inotifyItemBuf = buf;inotifyItemBuf < buf+numINotifyItem;) { + struct inotify_event *inotifyItem = (struct inotify_event *)inotifyItemBuf; + if (strstr(inotifyItem->name,"card")) { + //detect /dev/dri/card%d has been created + mCtx->enumKmsDisplays(); + EventListener* callback = NULL; + callback = mCtx->getCallback(); + if (callback != NULL) { + callback->onRefresh(0); + } + inotify_rm_watch(mINotifyFd,mINotifyWd); + close(mEpollFd); + close(mINotifyFd); + return false; + } + inotifyItemBuf += sizeof(struct inotify_event) + inotifyItem->len; + } + } + } + + return true; +} + } diff --git a/display/display/DisplayManager.h b/display/display/DisplayManager.h index b39e1fb..26cebf8 100644 --- a/display/display/DisplayManager.h +++ b/display/display/DisplayManager.h @@ -22,6 +22,10 @@ #include "VirtualDisplay.h" +#define BUFFER_SIZE 512 +#define DRM_DRI_PATH "/dev/dri/" +#define EPOLL_MAX_EVENTS 8 + #define MAX_PHYSICAL_DISPLAY 10 #define MAX_VIRTUAL_DISPLAY 16 @@ -48,6 +52,7 @@ public: int enumFakeKmsDisplay(); int enumKmsDisplays(); void setCallback(EventListener* callback); + EventListener* getCallback(); void handleHotplugEvent(); void handleKmsHotplug(); @@ -69,6 +74,23 @@ private: sp<HotplugThread> mHotplugThread; + class PollFileThread : public Thread { + public: + PollFileThread(DisplayManager *ctx); + + private: + virtual void onFirstRef(); + virtual int32_t readyToRun(); + virtual bool threadLoop(); + + DisplayManager *mCtx; + int mINotifyFd; + int mINotifyWd; + int mEpollFd; + }; + + sp<PollFileThread> mPollFileThread; + private: static Mutex sLock; static DisplayManager* sInstance;