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;