1 /* 2 // Copyright(c)2014 IntelCorporation 3 // 4 // LicensedundertheApacheLicense,Version2.0(the"License"); 5 // youmaynotusethisfileexceptincompliancewiththeLicense. 6 // YoumayobtainacopyoftheLicenseat 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unlessrequiredbyapplicablelaworagreedtoinwriting,software 11 // distributedundertheLicenseisdistributedonan"ASIS"BASIS, 12 // WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. 13 // SeetheLicenseforthespecificlanguagegoverningpermissionsand 14 // limitationsundertheLicense. 15 */ 16 #include <poll.h> 17 #include <sys/socket.h> 18 #include <sys/un.h> 19 #include <sys/queue.h> 20 #include <linux/netlink.h> 21 #include <sys/types.h> 22 #include <unistd.h> 23 #include <DrmConfig.h> 24 #include <HwcTrace.h> 25 #include <UeventObserver.h> 26 27 namespace android { 28 namespace intel { 29 30 UeventObserver::UeventObserver() 31 : mUeventFd(-1), 32 mExitRDFd(-1), 33 mExitWDFd(-1), 34 mListeners() 35 { 36 } 37 38 UeventObserver::~UeventObserver() 39 { 40 deinitialize(); 41 } 42 43 bool UeventObserver::initialize() 44 { 45 mListeners.clear(); 46 47 if (mUeventFd != -1) { 48 return true; 49 } 50 51 mThread = new UeventObserverThread(this); 52 if (!mThread.get()) { 53 ETRACE("failed to create uevent observer thread"); 54 return false; 55 } 56 57 // init uevent socket 58 struct sockaddr_nl addr; 59 // set the socket receive buffer to 64K 60 // NOTE: this is only called for once 61 int sz = 64 * 1024; 62 63 memset(&addr, 0, sizeof(addr)); 64 addr.nl_family = AF_NETLINK; 65 addr.nl_pid = pthread_self() | getpid(); 66 addr.nl_groups = 0xffffffff; 67 68 mUeventFd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); 69 if (mUeventFd < 0) { 70 DEINIT_AND_RETURN_FALSE("failed to create uevent socket"); 71 } 72 73 if (setsockopt(mUeventFd, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz))) { 74 WTRACE("setsockopt() failed"); 75 //return false; 76 } 77 78 if (bind(mUeventFd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 79 DEINIT_AND_RETURN_FALSE("failed to bind scoket"); 80 return false; 81 } 82 83 memset(mUeventMessage, 0, UEVENT_MSG_LEN); 84 85 int exitFds[2]; 86 if (pipe(exitFds) < 0) { 87 ETRACE("failed to make pipe"); 88 deinitialize(); 89 return false; 90 } 91 mExitRDFd = exitFds[0]; 92 mExitWDFd = exitFds[1]; 93 94 return true; 95 } 96 97 void UeventObserver::deinitialize() 98 { 99 if (mUeventFd != -1) { 100 if (mExitWDFd != -1) { 101 close(mExitWDFd); 102 mExitWDFd = -1; 103 } 104 close(mUeventFd); 105 mUeventFd = -1; 106 } 107 108 if (mThread.get()) { 109 mThread->requestExitAndWait(); 110 mThread = NULL; 111 } 112 113 while (!mListeners.isEmpty()) { 114 UeventListener *listener = mListeners.valueAt(0); 115 mListeners.removeItemsAt(0); 116 delete listener; 117 } 118 } 119 120 void UeventObserver::start() 121 { 122 if (mThread.get()) { 123 mThread->run("UeventObserver", PRIORITY_URGENT_DISPLAY); 124 } 125 } 126 127 128 void UeventObserver::registerListener(const char *event, UeventListenerFunc func, void *data) 129 { 130 if (!event || !func) { 131 ETRACE("invalid event string or listener to register"); 132 return; 133 } 134 135 String8 key(event); 136 if (mListeners.indexOfKey(key) >= 0) { 137 ETRACE("listener for uevent %s exists", event); 138 return; 139 } 140 141 UeventListener *listener = new UeventListener; 142 if (!listener) { 143 ETRACE("failed to create Uevent Listener"); 144 return; 145 } 146 listener->func = func; 147 listener->data = data; 148 149 mListeners.add(key, listener); 150 } 151 152 bool UeventObserver::threadLoop() 153 { 154 if (mUeventFd == -1) { 155 ETRACE("invalid uEvent file descriptor"); 156 return false; 157 } 158 159 struct pollfd fds[2]; 160 int nr; 161 162 fds[0].fd = mUeventFd; 163 fds[0].events = POLLIN; 164 fds[0].revents = 0; 165 fds[1].fd = mExitRDFd; 166 fds[1].events = POLLIN; 167 fds[1].revents = 0; 168 nr = poll(fds, 2, -1); 169 170 if (nr > 0 && fds[0].revents == POLLIN) { 171 int count = recv(mUeventFd, mUeventMessage, UEVENT_MSG_LEN - 2, 0); 172 if (count > 0) { 173 onUevent(); 174 } 175 } else if (fds[1].revents) { 176 close(mExitRDFd); 177 mExitRDFd = -1; 178 ITRACE("exiting wait"); 179 return false; 180 } 181 // always looping 182 return true; 183 } 184 185 void UeventObserver::onUevent() 186 { 187 char *msg = mUeventMessage; 188 const char *envelope = DrmConfig::getUeventEnvelope(); 189 if (strncmp(msg, envelope, strlen(envelope)) != 0) 190 return; 191 192 msg += strlen(msg) + 1; 193 194 UeventListener *listener; 195 String8 key; 196 while (*msg) { 197 key = String8(msg); 198 if (mListeners.indexOfKey(key) >= 0) { 199 DTRACE("received Uevent: %s", msg); 200 listener = mListeners.valueFor(key); 201 if (listener) { 202 listener->func(listener->data); 203 } else { 204 ETRACE("no listener for uevent %s", msg); 205 } 206 } 207 msg += strlen(msg) + 1; 208 } 209 } 210 211 } // namespace intel 212 } // namespace android 213 214