mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-20 00:20:37 +00:00
Bug 742226 - Add a uevent poller implementation. r=cjones
This commit is contained in:
parent
14c301c057
commit
077f479354
@ -84,6 +84,7 @@ CPPSRCS += \
|
||||
GonkHal.cpp \
|
||||
Power.cpp \
|
||||
GonkSensor.cpp \
|
||||
UeventPoller.cpp \
|
||||
$(NULL)
|
||||
else ifeq (Linux,$(OS_TARGET))
|
||||
CPPSRCS += \
|
||||
|
198
hal/gonk/UeventPoller.cpp
Normal file
198
hal/gonk/UeventPoller.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "base/message_loop.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#include "UeventPoller.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal_impl {
|
||||
|
||||
static void ShutdownUevent();
|
||||
|
||||
class NetlinkPoller : public MessageLoopForIO::Watcher
|
||||
{
|
||||
public:
|
||||
NetlinkPoller() : mSocket(-1),
|
||||
mIOLoop(MessageLoopForIO::current())
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~NetlinkPoller() {}
|
||||
|
||||
bool OpenSocket();
|
||||
|
||||
virtual void OnFileCanReadWithoutBlocking(int fd);
|
||||
|
||||
// no writing to the netlink socket
|
||||
virtual void OnFileCanWriteWithoutBlocking(int fd)
|
||||
{
|
||||
MOZ_NOT_REACHED("Must not write to netlink socket");
|
||||
}
|
||||
|
||||
MessageLoopForIO *GetIOLoop () const { return mIOLoop; }
|
||||
void RegisterObserver(IUeventObserver *aObserver)
|
||||
{
|
||||
mUeventObserverList.AddObserver(aObserver);
|
||||
}
|
||||
|
||||
void UnregisterObserver(IUeventObserver *aObserver)
|
||||
{
|
||||
mUeventObserverList.RemoveObserver(aObserver);
|
||||
if (mUeventObserverList.Length() == 0)
|
||||
ShutdownUevent(); // this will destroy self
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedClose mSocket;
|
||||
MessageLoopForIO* mIOLoop;
|
||||
MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
|
||||
|
||||
NetlinkEvent mNetlinkEvent;
|
||||
const static int kBuffsize = 64 * 1024;
|
||||
uint8_t mBuffer [kBuffsize];
|
||||
|
||||
typedef ObserverList<NetlinkEvent> UeventObserverList;
|
||||
UeventObserverList mUeventObserverList;
|
||||
};
|
||||
|
||||
bool
|
||||
NetlinkPoller::OpenSocket()
|
||||
{
|
||||
mSocket.mFd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
|
||||
if (mSocket.mFd < 0)
|
||||
return false;
|
||||
|
||||
int sz = kBuffsize;
|
||||
|
||||
if (setsockopt(mSocket.mFd, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0)
|
||||
return false;
|
||||
|
||||
// add FD_CLOEXEC flag
|
||||
int flags = fcntl(mSocket.mFd, F_GETFD);
|
||||
if (flags == -1) {
|
||||
return false;
|
||||
}
|
||||
flags |= FD_CLOEXEC;
|
||||
if (fcntl(mSocket.mFd, F_SETFD, flags) == -1)
|
||||
return false;
|
||||
|
||||
// set non-blocking
|
||||
if (fcntl(mSocket.mFd, F_SETFL, O_NONBLOCK) == -1)
|
||||
return false;
|
||||
|
||||
struct sockaddr_nl saddr;
|
||||
bzero(&saddr, sizeof(saddr));
|
||||
saddr.nl_family = AF_NETLINK;
|
||||
saddr.nl_groups = 1;
|
||||
saddr.nl_pid = getpid();
|
||||
|
||||
if (bind(mSocket.mFd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1)
|
||||
return false;
|
||||
|
||||
if (!mIOLoop->WatchFileDescriptor(mSocket.mFd,
|
||||
true,
|
||||
MessageLoopForIO::WATCH_READ,
|
||||
&mReadWatcher,
|
||||
this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static nsAutoPtr<NetlinkPoller> sPoller;
|
||||
|
||||
class UeventInitTask : public Task
|
||||
{
|
||||
virtual void Run()
|
||||
{
|
||||
if (!sPoller) {
|
||||
return;
|
||||
}
|
||||
if (sPoller->OpenSocket()) {
|
||||
return;
|
||||
}
|
||||
sPoller->GetIOLoop()->PostDelayedTask(FROM_HERE, new UeventInitTask(), 1000);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
NetlinkPoller::OnFileCanReadWithoutBlocking(int fd)
|
||||
{
|
||||
MOZ_ASSERT(fd == mSocket.mFd);
|
||||
while (true) {
|
||||
int ret = read(fd, mBuffer, kBuffsize);
|
||||
if (ret == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
return;
|
||||
}
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (ret <= 0) {
|
||||
// fatal error on netlink socket which should not happen
|
||||
_exit(1);
|
||||
}
|
||||
mNetlinkEvent.decode(reinterpret_cast<char*>(mBuffer), ret);
|
||||
mUeventObserverList.Broadcast(mNetlinkEvent);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
InitializeUevent()
|
||||
{
|
||||
MOZ_ASSERT(!sPoller);
|
||||
sPoller = new NetlinkPoller();
|
||||
sPoller->GetIOLoop()->PostTask(FROM_HERE, new UeventInitTask());
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
ShutdownUevent()
|
||||
{
|
||||
sPoller = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
RegisterUeventListener(IUeventObserver *aObserver)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||
|
||||
if (!sPoller)
|
||||
InitializeUevent();
|
||||
sPoller->RegisterObserver(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
UnregisterUeventListener(IUeventObserver *aObserver)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||
|
||||
sPoller->UnregisterObserver(aObserver);
|
||||
}
|
||||
|
||||
} // hal_impl
|
||||
} // mozilla
|
||||
|
38
hal/gonk/UeventPoller.h
Normal file
38
hal/gonk/UeventPoller.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _mozilla_uevent_poller_h_
|
||||
#define _mozilla_uevent_poller_h_
|
||||
|
||||
#include <sysutils/NetlinkEvent.h>
|
||||
#include "mozilla/Observer.h"
|
||||
|
||||
class NetlinkEvent;
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal_impl {
|
||||
|
||||
typedef mozilla::Observer<NetlinkEvent> IUeventObserver;
|
||||
|
||||
/**
|
||||
* Register for uevent notification. Note that the method should run on the
|
||||
* <b> IO Thread </b>
|
||||
* @aObserver the observer to be added. The observer's Notify() is only called
|
||||
* on the <b> IO Thread </b>
|
||||
*/
|
||||
void RegisterUeventListener(IUeventObserver *aObserver);
|
||||
|
||||
/**
|
||||
* Unregister for uevent notification. Note that the method should run on the
|
||||
* <b> IO Thread </b>
|
||||
* @aObserver the observer to be removed
|
||||
*/
|
||||
void UnregisterUeventListener(IUeventObserver *aObserver);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -395,6 +395,7 @@ OS_LIBS += \
|
||||
-lhardware \
|
||||
-lutils \
|
||||
-lcutils \
|
||||
-lsysutils \
|
||||
-lcamera_client \
|
||||
-lbinder \
|
||||
-lsensorservice \
|
||||
|
Loading…
x
Reference in New Issue
Block a user