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 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 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 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 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