• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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