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