libsysutils: Introduce 'ServiceManager', for starting/stopping init services

Signed-off-by: San Mehat <san@google.com>
diff --git a/include/sysutils/ServiceManager.h b/include/sysutils/ServiceManager.h
new file mode 100644
index 0000000..c31dd8f
--- /dev/null
+++ b/include/sysutils/ServiceManager.h
@@ -0,0 +1,30 @@
+/*
+ * 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 _SERVICE_MANAGER_H
+#define _SERVICE_MANAGER_H
+
+class ServiceManager {
+public:
+    ServiceManager();
+    virtual ~ServiceManager() {}
+
+    int start(const char *name);
+    int stop(const char *name);
+    bool isRunning(const char *name);
+};
+
+#endif
diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk
index 2f3e106..dd2b32d 100644
--- a/libsysutils/Android.mk
+++ b/libsysutils/Android.mk
@@ -16,6 +16,7 @@
                   src/NetlinkEvent.cpp        \
                   src/FrameworkCommand.cpp    \
                   src/SocketClient.cpp        \
+                  src/ServiceManager.cpp      \
 
 LOCAL_MODULE:= libsysutils
 
diff --git a/libsysutils/src/ServiceManager.cpp b/libsysutils/src/ServiceManager.cpp
new file mode 100644
index 0000000..700ac91
--- /dev/null
+++ b/libsysutils/src/ServiceManager.cpp
@@ -0,0 +1,73 @@
+#include <errno.h>
+
+#include <sysutils/ServiceManager.h>
+
+#define LOG_TAG "Service"
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+ServiceManager::ServiceManager() {
+}
+
+int ServiceManager::start(const char *name) {
+    if (isRunning(name)) {
+        LOGW("Service '%s' is already running", name);
+        return 0;
+    }
+
+    LOGD("Starting service '%s'", name);
+    property_set("ctl.start", name);
+
+    int count = 200;
+    while(count--) {
+        sched_yield();
+        if (isRunning(name))
+            break;
+    }
+    if (!count) {
+        LOGW("Timed out waiting for service '%s' to start", name);
+        errno = ETIMEDOUT;
+        return -1;
+    }
+    LOGD("Sucessfully started '%s'", name);
+    return 0;
+}
+
+int ServiceManager::stop(const char *name) {
+    if (!isRunning(name)) {
+        LOGW("Service '%s' is already stopped", name);
+        return 0;
+    }
+
+    LOGD("Stopping service '%s'", name);
+    property_set("ctl.stop", name);
+
+    int count = 200;
+    while(count--) {
+        sched_yield();
+        if (!isRunning(name))
+            break;
+    }
+
+    if (!count) {
+        LOGW("Timed out waiting for service '%s' to stop", name);
+        errno = ETIMEDOUT;
+        return -1;
+    }
+    LOGD("Sucessfully stopped '%s'", name);
+    return 0;
+}
+
+bool ServiceManager::isRunning(const char *name) {
+    char propVal[PROPERTY_VALUE_MAX];
+    char propName[255];
+
+    snprintf(propName, sizeof(propVal), "init.svc.%s", name);
+
+
+    if (property_get(propName, propVal, NULL)) {
+        if (!strcmp(propVal, "running"))
+            return true;
+    }
+    return false;
+}