Home | History | Annotate | Download | only in os
      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 
     44         State(String state) {
     45             sStates.put(state, this);
     46         }
     47     }
     48 
     49     private static Object sPropertyLock = new Object();
     50 
     51     static {
     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     public static void start(String name) {
     64         SystemProperties.set("ctl.start", name);
     65     }
     66 
     67     /** Request that the init daemon stop a named service. */
     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. */
     73     public static void restart(String name) {
     74         SystemProperties.set("ctl.restart", name);
     75     }
     76 
     77     /**
     78      * Return current state of given service.
     79      */
     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      */
     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      */
    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      */
    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      */
    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