• 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 android.compat.annotation.UnsupportedAppUsage;
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. */
63     @UnsupportedAppUsage
start(String name)64     public static void start(String name) {
65         SystemProperties.set("ctl.start", name);
66     }
67 
68     /** Request that the init daemon stop a named service. */
69     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
stop(String name)70     public static void stop(String name) {
71         SystemProperties.set("ctl.stop", name);
72     }
73 
74     /** Request that the init daemon restart a named service. */
restart(String name)75     public static void restart(String name) {
76         SystemProperties.set("ctl.restart", name);
77     }
78 
79     /**
80      * Return current state of given service.
81      */
getState(String service)82     public static State getState(String service) {
83         final String rawState = SystemProperties.get("init.svc." + service);
84         final State state = sStates.get(rawState);
85         if (state != null) {
86             return state;
87         } else {
88             return State.STOPPED;
89         }
90     }
91 
92     /**
93      * Check if given service is {@link State#STOPPED}.
94      */
isStopped(String service)95     public static boolean isStopped(String service) {
96         return State.STOPPED.equals(getState(service));
97     }
98 
99     /**
100      * Check if given service is {@link State#RUNNING}.
101      */
isRunning(String service)102     public static boolean isRunning(String service) {
103         return State.RUNNING.equals(getState(service));
104     }
105 
106     /**
107      * Wait until given service has entered specific state.
108      */
waitForState(String service, State state, long timeoutMillis)109     public static void waitForState(String service, State state, long timeoutMillis)
110             throws TimeoutException {
111         final long endMillis = SystemClock.elapsedRealtime() + timeoutMillis;
112         while (true) {
113             synchronized (sPropertyLock) {
114                 final State currentState = getState(service);
115                 if (state.equals(currentState)) {
116                     return;
117                 }
118 
119                 if (SystemClock.elapsedRealtime() >= endMillis) {
120                     throw new TimeoutException("Service " + service + " currently " + currentState
121                             + "; waited " + timeoutMillis + "ms for " + state);
122                 }
123 
124                 try {
125                     sPropertyLock.wait(timeoutMillis);
126                 } catch (InterruptedException e) {
127                 }
128             }
129         }
130     }
131 
132     /**
133      * Wait until any of given services enters {@link State#STOPPED}.
134      */
waitForAnyStopped(String... services)135     public static void waitForAnyStopped(String... services)  {
136         while (true) {
137             synchronized (sPropertyLock) {
138                 for (String service : services) {
139                     if (State.STOPPED.equals(getState(service))) {
140                         return;
141                     }
142                 }
143 
144                 try {
145                     sPropertyLock.wait();
146                 } catch (InterruptedException e) {
147                 }
148             }
149         }
150     }
151 }
152