19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.os; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkeyimport com.google.android.collect.Maps; 20088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 21088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkeyimport java.util.HashMap; 22088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkeyimport java.util.concurrent.TimeoutException; 23088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 24088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey/** 25088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * Controls and utilities for low-level {@code init} services. 26088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * 27088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * @hide 28088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 29088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkeypublic class SystemService { 30088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 31088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey private static HashMap<String, State> sStates = Maps.newHashMap(); 32088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 33088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** 34088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * State of a known {@code init} service. 35088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 36088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public enum State { 37088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey RUNNING("running"), 38088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey STOPPING("stopping"), 39088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey STOPPED("stopped"), 40088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey RESTARTING("restarting"); 41088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 42088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey State(String state) { 43088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey sStates.put(state, this); 44088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 45088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 46088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 47088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey private static Object sPropertyLock = new Object(); 48088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 49088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey static { 50088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey SystemProperties.addChangeCallback(new Runnable() { 51088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey @Override 52088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public void run() { 53088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey synchronized (sPropertyLock) { 54088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey sPropertyLock.notifyAll(); 55088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 56088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 57088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey }); 58088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 59088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 60088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** Request that the init daemon start a named service. */ 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void start(String name) { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SystemProperties.set("ctl.start", name); 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 64088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 65088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** Request that the init daemon stop a named service. */ 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void stop(String name) { 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SystemProperties.set("ctl.stop", name); 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6930d4d57e8ed421a7d910c86c96c5648c899c2c9bWink Saville 7030d4d57e8ed421a7d910c86c96c5648c899c2c9bWink Saville /** Request that the init daemon restart a named service. */ 7130d4d57e8ed421a7d910c86c96c5648c899c2c9bWink Saville public static void restart(String name) { 7230d4d57e8ed421a7d910c86c96c5648c899c2c9bWink Saville SystemProperties.set("ctl.restart", name); 7330d4d57e8ed421a7d910c86c96c5648c899c2c9bWink Saville } 74088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 75088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** 76088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * Return current state of given service. 77088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 78088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public static State getState(String service) { 79088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey final String rawState = SystemProperties.get("init.svc." + service); 80088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey final State state = sStates.get(rawState); 81088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey if (state != null) { 82088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey return state; 83088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } else { 84899223b97c9b0ae56a8211a46600914c0ecfd854Jeff Sharkey return State.STOPPED; 85088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 86088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 87088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 88088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** 89088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * Check if given service is {@link State#STOPPED}. 90088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 91088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public static boolean isStopped(String service) { 92088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey return State.STOPPED.equals(getState(service)); 93088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 94088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 95088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** 96088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * Check if given service is {@link State#RUNNING}. 97088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 98088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public static boolean isRunning(String service) { 99088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey return State.RUNNING.equals(getState(service)); 100088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 101088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 102088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** 103088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * Wait until given service has entered specific state. 104088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 105088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public static void waitForState(String service, State state, long timeoutMillis) 106088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey throws TimeoutException { 107088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey final long endMillis = SystemClock.elapsedRealtime() + timeoutMillis; 108088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey while (true) { 109088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey synchronized (sPropertyLock) { 110088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey final State currentState = getState(service); 111088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey if (state.equals(currentState)) { 112088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey return; 113088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 114088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 115088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey if (SystemClock.elapsedRealtime() >= endMillis) { 116088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey throw new TimeoutException("Service " + service + " currently " + currentState 117088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey + "; waited " + timeoutMillis + "ms for " + state); 118088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 119088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 120088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey try { 121088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey sPropertyLock.wait(timeoutMillis); 122088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } catch (InterruptedException e) { 123088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 124088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 125088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 126088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 127088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 128088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** 129088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * Wait until any of given services enters {@link State#STOPPED}. 130088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 131088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public static void waitForAnyStopped(String... services) { 132088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey while (true) { 133088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey synchronized (sPropertyLock) { 134088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey for (String service : services) { 135088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey if (State.STOPPED.equals(getState(service))) { 136088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey return; 137088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 138088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 139088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 140088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey try { 141088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey sPropertyLock.wait(); 142088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } catch (InterruptedException e) { 143088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 144088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 145088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 146088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 148