18b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol/* 28b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// Copyright (c) 2014 Intel Corporation 38b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// 48b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// Licensed under the Apache License, Version 2.0 (the "License"); 58b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// you may not use this file except in compliance with the License. 68b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// You may obtain a copy of the License at 78b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// 88b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// http://www.apache.org/licenses/LICENSE-2.0 98b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// 108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// Unless required by applicable law or agreed to in writing, software 118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// distributed under the License is distributed on an "AS IS" BASIS, 128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// See the License for the specific language governing permissions and 148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// limitations under the License. 158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol*/ 168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <poll.h> 178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <sys/socket.h> 188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <sys/un.h> 198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <sys/queue.h> 208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <linux/netlink.h> 218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <sys/types.h> 228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <unistd.h> 238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <DrmConfig.h> 248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <HwcTrace.h> 258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <UeventObserver.h> 268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolnamespace android { 288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolnamespace intel { 298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin PujolUeventObserver::UeventObserver() 318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol : mUeventFd(-1), 328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mExitRDFd(-1), 338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mExitWDFd(-1), 348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mListeners() 358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin PujolUeventObserver::~UeventObserver() 398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol deinitialize(); 418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool UeventObserver::initialize() 448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mListeners.clear(); 468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mUeventFd != -1) { 488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return true; 498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mThread = new UeventObserverThread(this); 528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (!mThread.get()) { 538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol ETRACE("failed to create uevent observer thread"); 548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return false; 558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 568b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol // init uevent socket 588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol struct sockaddr_nl addr; 598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol // set the socket receive buffer to 64K 608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol // NOTE: this is only called for once 618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol int sz = 64 * 1024; 628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol memset(&addr, 0, sizeof(addr)); 648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol addr.nl_family = AF_NETLINK; 658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol addr.nl_pid = pthread_self() | getpid(); 668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol addr.nl_groups = 0xffffffff; 678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mUeventFd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); 698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mUeventFd < 0) { 708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol DEINIT_AND_RETURN_FALSE("failed to create uevent socket"); 718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (setsockopt(mUeventFd, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz))) { 748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol WTRACE("setsockopt() failed"); 758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol //return false; 768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (bind(mUeventFd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol DEINIT_AND_RETURN_FALSE("failed to bind scoket"); 808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return false; 818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol memset(mUeventMessage, 0, UEVENT_MSG_LEN); 848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol int exitFds[2]; 868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (pipe(exitFds) < 0) { 878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol ETRACE("failed to make pipe"); 888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol deinitialize(); 898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return false; 908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mExitRDFd = exitFds[0]; 928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mExitWDFd = exitFds[1]; 938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return true; 958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid UeventObserver::deinitialize() 988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mUeventFd != -1) { 1008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mExitWDFd != -1) { 1018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol close(mExitWDFd); 1028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mExitWDFd = -1; 1038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol close(mUeventFd); 1058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mUeventFd = -1; 1068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mThread.get()) { 1098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mThread->requestExitAndWait(); 1108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mThread = NULL; 1118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol while (!mListeners.isEmpty()) { 1148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol UeventListener *listener = mListeners.valueAt(0); 1158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mListeners.removeItemsAt(0); 1168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol delete listener; 1178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 1198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid UeventObserver::start() 1218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 1228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mThread.get()) { 1238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mThread->run("UeventObserver", PRIORITY_URGENT_DISPLAY); 1248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 1268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid UeventObserver::registerListener(const char *event, UeventListenerFunc func, void *data) 1298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 1308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (!event || !func) { 1318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol ETRACE("invalid event string or listener to register"); 1328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return; 1338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol String8 key(event); 1368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mListeners.indexOfKey(key) >= 0) { 1378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol ETRACE("listener for uevent %s exists", event); 1388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return; 1398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol UeventListener *listener = new UeventListener; 1428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (!listener) { 1438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol ETRACE("failed to create Uevent Listener"); 1448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return; 1458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol listener->func = func; 1478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol listener->data = data; 1488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mListeners.add(key, listener); 1508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 1518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool UeventObserver::threadLoop() 1538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 1548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mUeventFd == -1) { 1558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol ETRACE("invalid uEvent file descriptor"); 1568b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return false; 1578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol struct pollfd fds[2]; 1608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol int nr; 1618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol fds[0].fd = mUeventFd; 1638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol fds[0].events = POLLIN; 1648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol fds[0].revents = 0; 1658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol fds[1].fd = mExitRDFd; 1668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol fds[1].events = POLLIN; 1678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol fds[1].revents = 0; 1688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol nr = poll(fds, 2, -1); 1698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (nr > 0 && fds[0].revents == POLLIN) { 1718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol int count = recv(mUeventFd, mUeventMessage, UEVENT_MSG_LEN - 2, 0); 1728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (count > 0) { 1738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol onUevent(); 1748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } else if (fds[1].revents) { 1768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol close(mExitRDFd); 1778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mExitRDFd = -1; 1788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol ITRACE("exiting wait"); 1798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return false; 1808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol // always looping 1828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return true; 1838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 1848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid UeventObserver::onUevent() 1868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 1878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol char *msg = mUeventMessage; 1888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol const char *envelope = DrmConfig::getUeventEnvelope(); 1898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (strncmp(msg, envelope, strlen(envelope)) != 0) 1908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return; 1918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol msg += strlen(msg) + 1; 1938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol UeventListener *listener; 1958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol String8 key; 1968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol while (*msg) { 1978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol key = String8(msg); 1988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mListeners.indexOfKey(key) >= 0) { 1998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol DTRACE("received Uevent: %s", msg); 2008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol listener = mListeners.valueFor(key); 2018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (listener) { 2028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol listener->func(listener->data); 2038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } else { 2048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol ETRACE("no listener for uevent %s", msg); 2058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 2068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 2078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol msg += strlen(msg) + 1; 2088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 2098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 2108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 2118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} // namespace intel 2128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} // namespace android 2138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 214