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