1 /* 2 * Copyright (C) 2006 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 package android.os; 18 19 import android.util.Slog; 20 21 import com.google.android.collect.Maps; 22 23 import java.util.HashMap; 24 import java.util.concurrent.TimeoutException; 25 26 /** 27 * Controls and utilities for low-level {@code init} services. 28 * 29 * @hide 30 */ 31 public class SystemService { 32 33 private static HashMap<String, State> sStates = Maps.newHashMap(); 34 35 /** 36 * State of a known {@code init} service. 37 */ 38 public enum State { 39 RUNNING("running"), 40 STOPPING("stopping"), 41 STOPPED("stopped"), 42 RESTARTING("restarting"); 43 State(String state)44 State(String state) { 45 sStates.put(state, this); 46 } 47 } 48 49 private static Object sPropertyLock = new Object(); 50 51 static { SystemProperties.addChangeCallback(new Runnable() { @Override public void run() { synchronized (sPropertyLock) { sPropertyLock.notifyAll(); } } })52 SystemProperties.addChangeCallback(new Runnable() { 53 @Override 54 public void run() { 55 synchronized (sPropertyLock) { 56 sPropertyLock.notifyAll(); 57 } 58 } 59 }); 60 } 61 62 /** Request that the init daemon start a named service. */ start(String name)63 public static void start(String name) { 64 SystemProperties.set("ctl.start", name); 65 } 66 67 /** Request that the init daemon stop a named service. */ stop(String name)68 public static void stop(String name) { 69 SystemProperties.set("ctl.stop", name); 70 } 71 72 /** Request that the init daemon restart a named service. */ restart(String name)73 public static void restart(String name) { 74 SystemProperties.set("ctl.restart", name); 75 } 76 77 /** 78 * Return current state of given service. 79 */ getState(String service)80 public static State getState(String service) { 81 final String rawState = SystemProperties.get("init.svc." + service); 82 final State state = sStates.get(rawState); 83 if (state != null) { 84 return state; 85 } else { 86 return State.STOPPED; 87 } 88 } 89 90 /** 91 * Check if given service is {@link State#STOPPED}. 92 */ isStopped(String service)93 public static boolean isStopped(String service) { 94 return State.STOPPED.equals(getState(service)); 95 } 96 97 /** 98 * Check if given service is {@link State#RUNNING}. 99 */ isRunning(String service)100 public static boolean isRunning(String service) { 101 return State.RUNNING.equals(getState(service)); 102 } 103 104 /** 105 * Wait until given service has entered specific state. 106 */ waitForState(String service, State state, long timeoutMillis)107 public static void waitForState(String service, State state, long timeoutMillis) 108 throws TimeoutException { 109 final long endMillis = SystemClock.elapsedRealtime() + timeoutMillis; 110 while (true) { 111 synchronized (sPropertyLock) { 112 final State currentState = getState(service); 113 if (state.equals(currentState)) { 114 return; 115 } 116 117 if (SystemClock.elapsedRealtime() >= endMillis) { 118 throw new TimeoutException("Service " + service + " currently " + currentState 119 + "; waited " + timeoutMillis + "ms for " + state); 120 } 121 122 try { 123 sPropertyLock.wait(timeoutMillis); 124 } catch (InterruptedException e) { 125 } 126 } 127 } 128 } 129 130 /** 131 * Wait until any of given services enters {@link State#STOPPED}. 132 */ waitForAnyStopped(String... services)133 public static void waitForAnyStopped(String... services) { 134 while (true) { 135 synchronized (sPropertyLock) { 136 for (String service : services) { 137 if (State.STOPPED.equals(getState(service))) { 138 return; 139 } 140 } 141 142 try { 143 sPropertyLock.wait(); 144 } catch (InterruptedException e) { 145 } 146 } 147 } 148 } 149 } 150