diff options
author | San Mehat <san@google.com> | 2009-05-06 11:14:21 -0700 |
---|---|---|
committer | San Mehat <san@google.com> | 2009-05-06 15:12:02 -0700 |
commit | 168415b822cae1f8b54ef09c41c11a9b97b87f40 (patch) | |
tree | 4265fda29301863478294812a3a53f4a13a72428 /libsysutils | |
parent | 770354d7e6cd471daed426fcf04bf7246e7cb18b (diff) | |
download | core-168415b822cae1f8b54ef09c41c11a9b97b87f40.tar.gz core-168415b822cae1f8b54ef09c41c11a9b97b87f40.tar.bz2 core-168415b822cae1f8b54ef09c41c11a9b97b87f40.zip |
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>
Diffstat (limited to 'libsysutils')
-rw-r--r-- | libsysutils/Android.mk | 21 | ||||
-rw-r--r-- | libsysutils/src/FrameworkCommand.cpp | 32 | ||||
-rw-r--r-- | libsysutils/src/FrameworkListener.cpp | 76 | ||||
-rw-r--r-- | libsysutils/src/FrameworkManager.cpp | 83 | ||||
-rw-r--r-- | libsysutils/src/NetlinkEvent.cpp | 93 | ||||
-rw-r--r-- | libsysutils/src/NetlinkListener.cpp | 53 | ||||
-rw-r--r-- | libsysutils/src/SocketListener.cpp | 127 |
7 files changed, 485 insertions, 0 deletions
diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk new file mode 100644 index 000000000..0b15c1269 --- /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 000000000..0444de5c6 --- /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 000000000..bbf3f3a5c --- /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 000000000..5dceb9f15 --- /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 000000000..69cd3e7bb --- /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 000000000..d8713418f --- /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 000000000..f92e30d78 --- /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; +} |