summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSan Mehat <san@google.com>2009-05-06 11:14:21 -0700
committerSan Mehat <san@google.com>2009-05-06 15:12:02 -0700
commit168415b822cae1f8b54ef09c41c11a9b97b87f40 (patch)
tree4265fda29301863478294812a3a53f4a13a72428
parent770354d7e6cd471daed426fcf04bf7246e7cb18b (diff)
downloadsystem_core-168415b822cae1f8b54ef09c41c11a9b97b87f40.zip
system_core-168415b822cae1f8b54ef09c41c11a9b97b87f40.tar.gz
system_core-168415b822cae1f8b54ef09c41c11a9b97b87f40.tar.bz2
libsysutils: New C++ system convenience library
This library contains re-usable classes for common system level daemons. Initial consumers of this library are 'nexus' and 'vold2' Signed-off-by: San Mehat <san@google.com>
-rw-r--r--Android.mk1
-rw-r--r--include/sysutils/FrameworkCommand.h37
-rw-r--r--include/sysutils/FrameworkListener.h37
-rw-r--r--include/sysutils/FrameworkManager.h40
-rw-r--r--include/sysutils/NetlinkEvent.h44
-rw-r--r--include/sysutils/NetlinkListener.h32
-rw-r--r--include/sysutils/SocketListener.h35
-rw-r--r--libsysutils/Android.mk21
-rw-r--r--libsysutils/src/FrameworkCommand.cpp32
-rw-r--r--libsysutils/src/FrameworkListener.cpp76
-rw-r--r--libsysutils/src/FrameworkManager.cpp83
-rw-r--r--libsysutils/src/NetlinkEvent.cpp93
-rw-r--r--libsysutils/src/NetlinkListener.cpp53
-rw-r--r--libsysutils/src/SocketListener.cpp127
14 files changed, 711 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
index 8b79ceb..fa2f6f8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -21,6 +21,7 @@ else
include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
adb \
libcutils \
+ libsysutils \
liblog \
libnetutils \
libpixelflinger \
diff --git a/include/sysutils/FrameworkCommand.h b/include/sysutils/FrameworkCommand.h
new file mode 100644
index 0000000..952e99a
--- /dev/null
+++ b/include/sysutils/FrameworkCommand.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __FRAMEWORK_CMD_HANDLER_H
+#define __FRAMEWORK_CMD_HANDLER_H
+
+#include "../../../frameworks/base/include/utils/List.h"
+
+
+class FrameworkCommand {
+private:
+ const char *mCommand;
+
+public:
+
+ FrameworkCommand(const char *cmd);
+ virtual ~FrameworkCommand() { }
+
+ virtual int runCommand(char *data);
+
+ const char *getCommand() { return mCommand; }
+};
+
+typedef android::List<FrameworkCommand *> FrameworkCommandCollection;
+#endif
diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h
new file mode 100644
index 0000000..1454a6f
--- /dev/null
+++ b/include/sysutils/FrameworkListener.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _FRAMEWORKSOCKETLISTENER_H
+#define _FRAMEWORKSOCKETLISTENER_H
+
+#include "SocketListener.h"
+#include "FrameworkCommand.h"
+
+class FrameworkListener : public SocketListener {
+private:
+ FrameworkCommandCollection *mCommands;
+
+public:
+ FrameworkListener(const char *socketName);
+ virtual ~FrameworkListener() {}
+
+protected:
+ void registerCmd(FrameworkCommand *cmd);
+ virtual bool onDataAvailable(int socket);
+
+private:
+ void dispatchCommand(char *cmd);
+};
+#endif
diff --git a/include/sysutils/FrameworkManager.h b/include/sysutils/FrameworkManager.h
new file mode 100644
index 0000000..8a24d33
--- /dev/null
+++ b/include/sysutils/FrameworkManager.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _FRAMEWORKMANAGER_H
+#define _FRAMEWORKMANAGER_H
+
+#include <pthread.h>
+
+class FrameworkListener;
+
+class FrameworkManager {
+ int mDoorbell; // Socket used to accept connections from framework
+ int mFwSock; // Socket used to communicate with framework
+ const char *mSocketName;
+
+ FrameworkListener *mListener;
+
+ pthread_mutex_t mWriteMutex;
+
+public:
+ FrameworkManager(FrameworkListener *Listener);
+ virtual ~FrameworkManager() {}
+
+ int run();
+ int sendMsg(char *msg);
+ int sendMsg(char *msg, char *data);
+};
+#endif
diff --git a/include/sysutils/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h
new file mode 100644
index 0000000..95e83a3
--- /dev/null
+++ b/include/sysutils/NetlinkEvent.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _NETLINKEVENT_H
+#define _NETLINKEVENT_H
+
+#define NL_PARAMS_MAX 32
+
+class NetlinkEvent {
+ int mSeq;
+ char *mPath;
+ int mAction;
+ char *mSubsystem;
+ char *mParams[NL_PARAMS_MAX];
+
+public:
+ const static int NlActionUnknown;
+ const static int NlActionAdd;
+ const static int NlActionRemove;
+ const static int NlActionChange;
+
+ NetlinkEvent();
+ virtual ~NetlinkEvent();
+
+ bool decode(char *buffer, int size);
+ const char *findParam(const char *paramName);
+
+ const char *getSubsystem() { return mSubsystem; }
+ int getAction() { return mAction; }
+};
+
+#endif
diff --git a/include/sysutils/NetlinkListener.h b/include/sysutils/NetlinkListener.h
new file mode 100644
index 0000000..8ac811c
--- /dev/null
+++ b/include/sysutils/NetlinkListener.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _NETLINKLISTENER_H
+#define _NETLINKLISTENER_H
+
+#include "SocketListener.h"
+
+class NetlinkEvent;
+
+class NetlinkListener : public SocketListener {
+ char mBuffer[64 * 1024];
+
+public:
+ NetlinkListener(int socket);
+ virtual ~NetlinkListener() {}
+protected:
+ virtual bool onDataAvailable(int socket);
+};
+#endif
diff --git a/include/sysutils/SocketListener.h b/include/sysutils/SocketListener.h
new file mode 100644
index 0000000..f079dba
--- /dev/null
+++ b/include/sysutils/SocketListener.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _SOCKETLISTENER_H
+#define _SOCKETLISTENER_H
+
+class SocketListener {
+ int mSock;
+ int mCsock;
+ int mAcceptClients;
+ const char *mSocketName;
+
+public:
+ SocketListener(const char *socketName, bool acceptClients);
+ SocketListener(int socketFd, bool acceptClients);
+
+ virtual ~SocketListener() {}
+ virtual int run();
+
+protected:
+ virtual bool onDataAvailable(int socket);
+};
+#endif
diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk
new file mode 100644
index 0000000..0b15c12
--- /dev/null
+++ b/libsysutils/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ src/FrameworkManager.cpp \
+ src/SocketListener.cpp \
+ src/FrameworkListener.cpp \
+ src/NetlinkListener.cpp \
+ src/NetlinkEvent.cpp \
+ src/FrameworkCommand.cpp \
+
+LOCAL_MODULE:= libsysutils
+
+LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
+
+LOCAL_CFLAGS :=
+
+LOCAL_SHARED_LIBRARIES := libcutils
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libsysutils/src/FrameworkCommand.cpp b/libsysutils/src/FrameworkCommand.cpp
new file mode 100644
index 0000000..0444de5
--- /dev/null
+++ b/libsysutils/src/FrameworkCommand.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <errno.h>
+
+#define LOG_TAG "FrameworkCommand"
+
+#include <cutils/log.h>
+
+#include <sysutils/FrameworkCommand.h>
+
+FrameworkCommand::FrameworkCommand(const char *cmd) {
+ mCommand = cmd;
+}
+
+int FrameworkCommand::runCommand(char *data) {
+ LOGW("Command %s has no run handler!", getCommand());
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp
new file mode 100644
index 0000000..bbf3f3a
--- /dev/null
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <errno.h>
+
+#define LOG_TAG "FrameworkListener"
+
+#include <cutils/log.h>
+
+#include <sysutils/FrameworkListener.h>
+#include <sysutils/FrameworkCommand.h>
+
+FrameworkListener::FrameworkListener(const char *socketName) :
+ SocketListener(socketName, true) {
+ mCommands = new FrameworkCommandCollection();
+}
+
+bool FrameworkListener::onDataAvailable(int socket) {
+ char buffer[101];
+ int len;
+
+ if ((len = read(socket, buffer, sizeof(buffer) -1)) < 0) {
+ LOGE("read() failed (%s)", strerror(errno));
+ return errno;
+ } else if (!len) {
+ LOGW("Lost connection to client");
+ return false;
+ }
+
+ int start = 0;
+ int i;
+
+ buffer[len] = '\0';
+
+ for (i = 0; i < len; i++) {
+ if (buffer[i] == '\0') {
+ dispatchCommand(buffer + start);
+ start = i + 1;
+ }
+ }
+ return true;
+}
+
+void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
+ mCommands->push_back(cmd);
+}
+
+void FrameworkListener::dispatchCommand(char *cmd) {
+ FrameworkCommandCollection::iterator i;
+
+ for (i = mCommands->begin(); i != mCommands->end(); ++i) {
+ FrameworkCommand *c = *i;
+
+ if (!strncmp(cmd, c->getCommand(), strlen(c->getCommand()))) {
+ if (c->runCommand(cmd)) {
+ LOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
+ }
+ return;
+ }
+ }
+
+ LOGE("No cmd handlers defined for '%s'", cmd);
+}
+
diff --git a/libsysutils/src/FrameworkManager.cpp b/libsysutils/src/FrameworkManager.cpp
new file mode 100644
index 0000000..5dceb9f
--- /dev/null
+++ b/libsysutils/src/FrameworkManager.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include <cutils/config_utils.h>
+#include <cutils/cpu_info.h>
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+
+#define LOG_TAG "FrameworkManager"
+#include <cutils/log.h>
+
+#include <sysutils/FrameworkManager.h>
+#include <sysutils/FrameworkListener.h>
+
+FrameworkManager::FrameworkManager(FrameworkListener *Listener) {
+ mDoorbell = -1;
+ mFwSock = -1;
+ mListener = Listener;
+
+ pthread_mutex_init(&mWriteMutex, NULL);
+}
+
+int FrameworkManager::run() {
+
+ if (mListener->run()) {
+ LOGE("Error running listener (%s)", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+/* ========
+ * Privates
+ * ========
+ */
+
+int FrameworkManager::sendMsg(char *msg) {
+ LOGD("FrameworkManager::sendMsg(%s)", msg);
+ if (mFwSock < 0) {
+ errno = EHOSTUNREACH;
+ return -1;
+ }
+
+ pthread_mutex_lock(&mWriteMutex);
+ if (write(mFwSock, msg, strlen(msg) +1) < 0) {
+ LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno));
+ }
+ pthread_mutex_unlock(&mWriteMutex);
+ return 0;
+}
+
+int FrameworkManager::sendMsg(char *msg, char *data) {
+ char *buffer = (char *) alloca(strlen(msg) + strlen(data) + 1);
+ if (!buffer) {
+ errno = -ENOMEM;
+ return -1;
+ }
+ strcpy(buffer, msg);
+ strcat(buffer, data);
+ return sendMsg(buffer);
+}
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
new file mode 100644
index 0000000..69cd3e7
--- /dev/null
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdlib.h>
+
+#define LOG_TAG "NetlinkEvent"
+#include <cutils/log.h>
+
+#include <sysutils/NetlinkEvent.h>
+
+const int NetlinkEvent::NlActionUnknown = 0;
+const int NetlinkEvent::NlActionAdd = 1;
+const int NetlinkEvent::NlActionRemove = 2;
+const int NetlinkEvent::NlActionChange = 3;
+
+NetlinkEvent::NetlinkEvent() {
+ mAction = NlActionUnknown;
+}
+
+NetlinkEvent::~NetlinkEvent() {
+ int i;
+ if (mPath)
+ free(mPath);
+ if (mSubsystem)
+ free(mSubsystem);
+ for (i = 0; i < NL_PARAMS_MAX; i++) {
+ if (!mParams[i])
+ break;
+ free(mParams[i]);
+ }
+}
+
+bool NetlinkEvent::decode(char *buffer, int size) {
+ char *s = buffer;
+ char *end;
+ int param_idx = 0;
+ int i;
+ int first = 1;
+
+ end = s + size;
+ while (s < end) {
+ if (first) {
+ char *p;
+ for (p = s; *p != '@'; p++);
+ p++;
+ mPath = strdup(p);
+ first = 0;
+ } else {
+ if (!strncmp(s, "ACTION=", strlen("ACTION="))) {
+ char *a = s + strlen("ACTION=");
+ if (!strcmp(a, "add"))
+ mAction = NlActionAdd;
+ else if (!strcmp(a, "remove"))
+ mAction = NlActionRemove;
+ else if (!strcmp(a, "change"))
+ mAction = NlActionChange;
+ } else if (!strncmp(s, "SEQNUM=", strlen("SEQNUM=")))
+ mSeq = atoi(s + strlen("SEQNUM="));
+ else if (!strncmp(s, "SUBSYSTEM=", strlen("SUBSYSTEM=")))
+ mSubsystem = strdup(s + strlen("SUBSYSTEM="));
+ else
+ mParams[param_idx++] = strdup(s);
+ }
+ s+= strlen(s) + 1;
+ }
+ return true;
+}
+
+const char *NetlinkEvent::findParam(const char *paramName) {
+ int i;
+
+ for (i = 0; i < NL_PARAMS_MAX; i++) {
+ if (!mParams[i])
+ break;
+ if (!strncmp(mParams[i], paramName, strlen(paramName)))
+ return &mParams[i][strlen(paramName) + 1];
+ }
+
+ LOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName);
+ return NULL;
+}
diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp
new file mode 100644
index 0000000..d871341
--- /dev/null
+++ b/libsysutils/src/NetlinkListener.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#define LOG_TAG "NetlinkListener"
+#include <cutils/log.h>
+
+#include <sysutils/NetlinkListener.h>
+#include <sysutils/NetlinkEvent.h>
+
+NetlinkListener::NetlinkListener(int socket) :
+ SocketListener(socket, false) {
+}
+
+bool NetlinkListener::onDataAvailable(int socket)
+{
+ LOGD("NetlinkListener::onDataAvailable()");
+
+ int count;
+
+ if ((count = recv(socket, mBuffer, sizeof(mBuffer), 0)) < 0) {
+ LOGE("recv failed (%s)", strerror(errno));
+ return false;
+ }
+
+ NetlinkEvent *evt = new NetlinkEvent();
+ if (!evt->decode(mBuffer, count)) {
+ LOGE("Error decoding NetlinkEvent");
+ goto out;
+ }
+
+ LOGD("Ignoring '%s' netlink event", evt->getSubsystem());
+
+out:
+ delete evt;
+ return true;
+}
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
new file mode 100644
index 0000000..f92e30d
--- /dev/null
+++ b/libsysutils/src/SocketListener.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#define LOG_TAG "SocketListener"
+#include <cutils/log.h>
+
+#include <cutils/sockets.h>
+
+#include <sysutils/SocketListener.h>
+
+SocketListener::SocketListener(const char *socketName, bool acceptClients) {
+ mAcceptClients = acceptClients;
+ mCsock = -1;
+ mSocketName = socketName;
+ mSock = -1;
+}
+
+SocketListener::SocketListener(int socketFd, bool acceptClients) {
+ mAcceptClients = acceptClients;
+ mCsock = -1;
+ mSocketName = NULL;
+ mSock = socketFd;
+}
+
+int SocketListener::run() {
+
+ if (!mSocketName && mSock == -1) {
+ errno = EINVAL;
+ return -1;
+ } else if (mSocketName) {
+ if ((mSock = android_get_control_socket(mSocketName)) < 0) {
+ LOGE("Obtaining file descriptor socket '%s' failed: %s",
+ mSocketName, strerror(errno));
+ return -1;
+ }
+ }
+
+ if (mAcceptClients) {
+ if (listen(mSock, 4) < 0) {
+ LOGE("Unable to listen on socket (%s)", strerror(errno));
+ return -1;
+ }
+ }
+
+ while(1) {
+ fd_set read_fds;
+ struct timeval to;
+ int max = 0;
+ int rc = 0;
+
+ to.tv_sec = 60 * 60;
+ to.tv_usec = 0;
+
+ FD_ZERO(&read_fds);
+
+ if ((mAcceptClients == false) ||
+ (mAcceptClients == true && mCsock == -1)) {
+ FD_SET(mSock, &read_fds);
+ max = mSock;
+ } else if (mCsock != -1) {
+ FD_SET(mCsock, &read_fds);
+ max = mCsock;
+ }
+
+ if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) {
+ LOGE("select failed (%s)", strerror(errno));
+ return -errno;
+ } else if (!rc)
+ continue;
+ else if (FD_ISSET(mSock, &read_fds)) {
+ /*
+ * If we're accepting client connections then
+ * accept and gobble the event. Otherwise
+ * pass it on to the handlers.
+ */
+ if (mAcceptClients) {
+ struct sockaddr addr;
+ socklen_t alen = sizeof(addr);
+
+ if ((mCsock = accept(mSock, &addr, &alen)) < 0) {
+ LOGE("accept failed (%s)", strerror(errno));
+ return -errno;
+ }
+ LOGD("SocketListener client connection accepted");
+ } else if (!onDataAvailable(mSock)) {
+ LOGW("SocketListener closing listening socket (Will shut down)");
+ close(mSock);
+ return -ESHUTDOWN;
+ }
+ } else if ((FD_ISSET(mCsock, &read_fds)) &&
+ !onDataAvailable(mCsock)) {
+ /*
+ * Once mCsock == -1, we'll start
+ * accepting connections on mSock again.
+ */
+ LOGD("SocketListener closing client socket");
+ close(mCsock);
+ mCsock = -1;
+ }
+ }
+ return 0;
+}
+
+bool SocketListener::onDataAvailable(int socket) {
+ return false;
+}