1 #include <errno.h>
2 #include <string.h>
3
4 #include <sysutils/ServiceManager.h>
5
6 #define LOG_TAG "Service"
7 #include <cutils/log.h>
8 #include <cutils/properties.h>
9
ServiceManager()10 ServiceManager::ServiceManager() {
11 }
12
13 /* The service name should not exceed SERVICE_NAME_MAX to avoid
14 * some weird things. This is due to the fact that:
15 *
16 * - Starting a service is done by writing its name to the "ctl.start"
17 * system property. This triggers the init daemon to actually start
18 * the service for us.
19 *
20 * - Stopping the service is done by writing its name to "ctl.stop"
21 * in a similar way.
22 *
23 * - Reading the status of a service is done by reading the property
24 * named "init.svc.<name>"
25 *
26 * If strlen(<name>) > (PROPERTY_KEY_MAX-1)-9, then you can start/stop
27 * the service by writing to ctl.start/stop, but you won't be able to
28 * read its state due to the truncation of "init.svc.<name>" into a
29 * zero-terminated buffer of PROPERTY_KEY_MAX characters.
30 */
31 #define SERVICE_NAME_MAX (PROPERTY_KEY_MAX-10)
32
33 /* The maximum amount of time to wait for a service to start or stop,
34 * in micro-seconds (really an approximation) */
35 #define SLEEP_MAX_USEC 2000000 /* 2 seconds */
36
37 /* The minimal sleeping interval between checking for the service's state
38 * when looping for SLEEP_MAX_USEC */
39 #define SLEEP_MIN_USEC 200000 /* 200 msec */
40
start(const char * name)41 int ServiceManager::start(const char *name) {
42 if (strlen(name) > SERVICE_NAME_MAX) {
43 SLOGE("Service name '%s' is too long", name);
44 return 0;
45 }
46 if (isRunning(name)) {
47 SLOGW("Service '%s' is already running", name);
48 return 0;
49 }
50
51 SLOGD("Starting service '%s'", name);
52 property_set("ctl.start", name);
53
54 int count = SLEEP_MAX_USEC;
55 while(count > 0) {
56 usleep(SLEEP_MIN_USEC);
57 count -= SLEEP_MIN_USEC;
58 if (isRunning(name))
59 break;
60 }
61 if (count <= 0) {
62 SLOGW("Timed out waiting for service '%s' to start", name);
63 errno = ETIMEDOUT;
64 return -1;
65 }
66 SLOGD("Sucessfully started '%s'", name);
67 return 0;
68 }
69
stop(const char * name)70 int ServiceManager::stop(const char *name) {
71 if (strlen(name) > SERVICE_NAME_MAX) {
72 SLOGE("Service name '%s' is too long", name);
73 return 0;
74 }
75 if (!isRunning(name)) {
76 SLOGW("Service '%s' is already stopped", name);
77 return 0;
78 }
79
80 SLOGD("Stopping service '%s'", name);
81 property_set("ctl.stop", name);
82
83 int count = SLEEP_MAX_USEC;
84 while(count > 0) {
85 usleep(SLEEP_MIN_USEC);
86 count -= SLEEP_MIN_USEC;
87 if (!isRunning(name))
88 break;
89 }
90
91 if (count <= 0) {
92 SLOGW("Timed out waiting for service '%s' to stop", name);
93 errno = ETIMEDOUT;
94 return -1;
95 }
96 SLOGD("Successfully stopped '%s'", name);
97 return 0;
98 }
99
isRunning(const char * name)100 bool ServiceManager::isRunning(const char *name) {
101 char propVal[PROPERTY_VALUE_MAX];
102 char propName[PROPERTY_KEY_MAX];
103 int ret;
104
105 ret = snprintf(propName, sizeof(propName), "init.svc.%s", name);
106 if (ret > (int)sizeof(propName)-1) {
107 SLOGD("Service name '%s' is too long", name);
108 return false;
109 }
110
111 if (property_get(propName, propVal, NULL)) {
112 if (!strcmp(propVal, "running"))
113 return true;
114 }
115 return false;
116 }
117