1 /* 2 * Copyright (C) 2009-2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "Service" 18 19 #include <errno.h> 20 #include <stdio.h> 21 #include <string.h> 22 #include <sys/system_properties.h> 23 #include <unistd.h> 24 25 #include <android-base/properties.h> 26 #include <android-base/stringprintf.h> 27 #include <log/log.h> 28 #include <sysutils/ServiceManager.h> 29 30 ServiceManager::ServiceManager() { 31 } 32 33 // The length of a service name should not exceed SERVICE_NAME_MAX. Starting 34 // a service is done by writing its name to the "ctl.start" system property 35 // and stopping a service is done by writing its name to "ctl.stop". If a 36 // service name is too long to fit in a property, you won't be able to start 37 // or stop it. 38 static constexpr size_t SERVICE_NAME_MAX = PROP_VALUE_MAX; 39 40 /* The maximum amount of time to wait for a service to start or stop, 41 * in micro-seconds (really an approximation) */ 42 #define SLEEP_MAX_USEC 2000000 /* 2 seconds */ 43 44 /* The minimal sleeping interval between checking for the service's state 45 * when looping for SLEEP_MAX_USEC */ 46 #define SLEEP_MIN_USEC 200000 /* 200 msec */ 47 48 int ServiceManager::start(const char *name) { 49 if (strlen(name) > SERVICE_NAME_MAX) { 50 SLOGE("Service name '%s' is too long", name); 51 return 0; 52 } 53 54 if (isRunning(name)) { 55 SLOGW("Service '%s' is already running", name); 56 return 0; 57 } 58 59 SLOGD("Starting service '%s'", name); 60 android::base::SetProperty("ctl.start", name); 61 62 int count = SLEEP_MAX_USEC; 63 while(count > 0) { 64 usleep(SLEEP_MIN_USEC); 65 count -= SLEEP_MIN_USEC; 66 if (isRunning(name)) 67 break; 68 } 69 if (count <= 0) { 70 SLOGW("Timed out waiting for service '%s' to start", name); 71 errno = ETIMEDOUT; 72 return -1; 73 } 74 SLOGD("Sucessfully started '%s'", name); 75 return 0; 76 } 77 78 int ServiceManager::stop(const char *name) { 79 if (strlen(name) > SERVICE_NAME_MAX) { 80 SLOGE("Service name '%s' is too long", name); 81 return 0; 82 } 83 84 if (!isRunning(name)) { 85 SLOGW("Service '%s' is already stopped", name); 86 return 0; 87 } 88 89 SLOGD("Stopping service '%s'", name); 90 android::base::SetProperty("ctl.stop", name); 91 92 int count = SLEEP_MAX_USEC; 93 while(count > 0) { 94 usleep(SLEEP_MIN_USEC); 95 count -= SLEEP_MIN_USEC; 96 if (!isRunning(name)) 97 break; 98 } 99 100 if (count <= 0) { 101 SLOGW("Timed out waiting for service '%s' to stop", name); 102 errno = ETIMEDOUT; 103 return -1; 104 } 105 SLOGD("Successfully stopped '%s'", name); 106 return 0; 107 } 108 109 bool ServiceManager::isRunning(const char *name) { 110 std::string property_name = android::base::StringPrintf("init.svc.%s", name); 111 return (android::base::GetProperty(property_name, "") == "running"); 112 } 113