16a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu/* 2cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// Copyright (c) 2014 Intel Corporation 3cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// 4cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// Licensed under the Apache License, Version 2.0 (the "License"); 5cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// you may not use this file except in compliance with the License. 6cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// You may obtain a copy of the License at 7cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// 8cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// http://www.apache.org/licenses/LICENSE-2.0 9cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// 10cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// Unless required by applicable law or agreed to in writing, software 11cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// distributed under the License is distributed on an "AS IS" BASIS, 12cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// See the License for the specific language governing permissions and 14cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// limitations under the License. 15cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika*/ 166a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu#include <poll.h> 176a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu#include <sys/socket.h> 186a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu#include <sys/un.h> 196a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu#include <sys/queue.h> 206a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu#include <linux/netlink.h> 216a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu#include <sys/types.h> 226a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu#include <unistd.h> 23877d4ac27c6fde0b89b68e7c6e352edf879b3dedAndy Qiu#include <DrmConfig.h> 240594c42af26255fd8d3d7d39c0cb0e2da5b8841bThierry Strudel#include <common/utils/HwcTrace.h> 25466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu#include <UeventObserver.h> 266a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 276a6081a46a83da606cf21548879b37695adc7e1fAndy Qiunamespace android { 286a6081a46a83da606cf21548879b37695adc7e1fAndy Qiunamespace intel { 296a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 30466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin HuUeventObserver::UeventObserver() 31466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu : mUeventFd(-1), 32375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei mExitRDFd(-1), 33375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei mExitWDFd(-1), 34466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu mListeners() 356a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu{ 36eb726af21649d79ed720bdf329e0849270995c45Andy Qiu} 37eb726af21649d79ed720bdf329e0849270995c45Andy Qiu 38466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin HuUeventObserver::~UeventObserver() 39eb726af21649d79ed720bdf329e0849270995c45Andy Qiu{ 40466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu deinitialize(); 41eb726af21649d79ed720bdf329e0849270995c45Andy Qiu} 42eb726af21649d79ed720bdf329e0849270995c45Andy Qiu 43466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hubool UeventObserver::initialize() 44eb726af21649d79ed720bdf329e0849270995c45Andy Qiu{ 45466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu mListeners.clear(); 46466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu 47eb726af21649d79ed720bdf329e0849270995c45Andy Qiu if (mUeventFd != -1) { 48eb726af21649d79ed720bdf329e0849270995c45Andy Qiu return true; 49eb726af21649d79ed720bdf329e0849270995c45Andy Qiu } 506a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 51466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu mThread = new UeventObserverThread(this); 52466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu if (!mThread.get()) { 534157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev ELOGTRACE("failed to create uevent observer thread"); 54466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu return false; 55466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu } 56466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu 576a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu // init uevent socket 586a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu struct sockaddr_nl addr; 59e6ecdadd57e79c2218b3e6ae407f12599f33bd22Jackie Li // set the socket receive buffer to 64K 60e6ecdadd57e79c2218b3e6ae407f12599f33bd22Jackie Li // NOTE: this is only called for once 61e6ecdadd57e79c2218b3e6ae407f12599f33bd22Jackie Li int sz = 64 * 1024; 626a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 636a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu memset(&addr, 0, sizeof(addr)); 646a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu addr.nl_family = AF_NETLINK; 656a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu addr.nl_pid = pthread_self() | getpid(); 666a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu addr.nl_groups = 0xffffffff; 676a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 686a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu mUeventFd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); 69eb726af21649d79ed720bdf329e0849270995c45Andy Qiu if (mUeventFd < 0) { 70466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu DEINIT_AND_RETURN_FALSE("failed to create uevent socket"); 716a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu } 726a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 73466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu if (setsockopt(mUeventFd, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz))) { 744157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev WLOGTRACE("setsockopt() failed"); 75466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu //return false; 76466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu } 776a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 78eb726af21649d79ed720bdf329e0849270995c45Andy Qiu if (bind(mUeventFd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 79466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu DEINIT_AND_RETURN_FALSE("failed to bind scoket"); 80eb726af21649d79ed720bdf329e0849270995c45Andy Qiu return false; 816a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu } 826a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 836a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu memset(mUeventMessage, 0, UEVENT_MSG_LEN); 84375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei 85375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei int exitFds[2]; 86375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei if (pipe(exitFds) < 0) { 874157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev ELOGTRACE("failed to make pipe"); 88375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei deinitialize(); 89375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei return false; 90375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei } 91375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei mExitRDFd = exitFds[0]; 92375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei mExitWDFd = exitFds[1]; 93375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei 94eb726af21649d79ed720bdf329e0849270995c45Andy Qiu return true; 956a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu} 966a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 97466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Huvoid UeventObserver::deinitialize() 986a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu{ 99eb726af21649d79ed720bdf329e0849270995c45Andy Qiu if (mUeventFd != -1) { 100375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei if (mExitWDFd != -1) { 101375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei close(mExitWDFd); 102375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei mExitWDFd = -1; 103375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei } 104eb726af21649d79ed720bdf329e0849270995c45Andy Qiu close(mUeventFd); 105eb726af21649d79ed720bdf329e0849270995c45Andy Qiu mUeventFd = -1; 106eb726af21649d79ed720bdf329e0849270995c45Andy Qiu } 107466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu 108466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu if (mThread.get()) { 109466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu mThread->requestExitAndWait(); 110466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu mThread = NULL; 111466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu } 112466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu 113466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu while (!mListeners.isEmpty()) { 114466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu UeventListener *listener = mListeners.valueAt(0); 115466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu mListeners.removeItemsAt(0); 116466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu delete listener; 117466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu } 118466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu} 119466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu 120466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Huvoid UeventObserver::start() 121466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu{ 122466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu if (mThread.get()) { 123466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu mThread->run("UeventObserver", PRIORITY_URGENT_DISPLAY); 124466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu } 125466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu} 126466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu 127466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu 128466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Huvoid UeventObserver::registerListener(const char *event, UeventListenerFunc func, void *data) 129466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu{ 130466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu if (!event || !func) { 1314157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev ELOGTRACE("invalid event string or listener to register"); 132466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu return; 133466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu } 134466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu 135466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu String8 key(event); 136466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu if (mListeners.indexOfKey(key) >= 0) { 1374157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev ELOGTRACE("listener for uevent %s exists", event); 138466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu return; 139466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu } 140466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu 141466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu UeventListener *listener = new UeventListener; 142466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu if (!listener) { 1434157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev ELOGTRACE("failed to create Uevent Listener"); 144466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu return; 145466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu } 146466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu listener->func = func; 147466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu listener->data = data; 148466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu 149466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu mListeners.add(key, listener); 1506a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu} 1516a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 152466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hubool UeventObserver::threadLoop() 1536a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu{ 154eb726af21649d79ed720bdf329e0849270995c45Andy Qiu if (mUeventFd == -1) { 1554157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev ELOGTRACE("invalid uEvent file descriptor"); 156eb726af21649d79ed720bdf329e0849270995c45Andy Qiu return false; 157eb726af21649d79ed720bdf329e0849270995c45Andy Qiu } 158eb726af21649d79ed720bdf329e0849270995c45Andy Qiu 159375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei struct pollfd fds[2]; 1606a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu int nr; 1616a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 162375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei fds[0].fd = mUeventFd; 163375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei fds[0].events = POLLIN; 164375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei fds[0].revents = 0; 165375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei fds[1].fd = mExitRDFd; 166375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei fds[1].events = POLLIN; 167375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei fds[1].revents = 0; 168375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei nr = poll(fds, 2, -1); 1696a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 170375f3cbb9faa54c3419bd835c41387ca1b0da0b2Tan Wei if (nr > 0 && fds[0].revents == POLLIN) { 1716a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu int count = recv(mUeventFd, mUeventMessage, UEVENT_MSG_LEN - 2, 0); 172466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu if (count > 0) { 173466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu onUevent(); 174466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu } 175123770a44b11572ea9c0fcbb236eabfc2892bdf8Tan Wei } else if (fds[1].revents) { 176123770a44b11572ea9c0fcbb236eabfc2892bdf8Tan Wei close(mExitRDFd); 177123770a44b11572ea9c0fcbb236eabfc2892bdf8Tan Wei mExitRDFd = -1; 1784157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev ILOGTRACE("exiting wait"); 179123770a44b11572ea9c0fcbb236eabfc2892bdf8Tan Wei return false; 1806a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu } 181466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu // always looping 182466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu return true; 1836a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu} 1846a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 185466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Huvoid UeventObserver::onUevent() 1866a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu{ 187466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu char *msg = mUeventMessage; 188466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu const char *envelope = DrmConfig::getUeventEnvelope(); 189466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu if (strncmp(msg, envelope, strlen(envelope)) != 0) 190466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu return; 1916a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 1926a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu msg += strlen(msg) + 1; 1936a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 194466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu UeventListener *listener; 195466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu String8 key; 196466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu while (*msg) { 197466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu key = String8(msg); 198466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu if (mListeners.indexOfKey(key) >= 0) { 1994157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev DLOGTRACE("received Uevent: %s", msg); 200466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu listener = mListeners.valueFor(key); 201466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu if (listener) { 202466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu listener->func(listener->data); 203466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu } else { 2044157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev ELOGTRACE("no listener for uevent %s", msg); 205466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu } 2066a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu } 2076a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu msg += strlen(msg) + 1; 208466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu } 2096a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu} 2106a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu 2116a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu} // namespace intel 2126a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu} // namespace android 213466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu 214