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