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 19899223b97c9b0ae56a8211a46600914c0ecfd854Jeff Sharkeyimport android.util.Slog; 20899223b97c9b0ae56a8211a46600914c0ecfd854Jeff Sharkey 21088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkeyimport com.google.android.collect.Maps; 22088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 23088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkeyimport java.util.HashMap; 24088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkeyimport java.util.concurrent.TimeoutException; 25088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 26088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey/** 27088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * Controls and utilities for low-level {@code init} services. 28088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * 29088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * @hide 30088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 31088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkeypublic class SystemService { 32088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 33088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey private static HashMap<String, State> sStates = Maps.newHashMap(); 34088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 35088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** 36088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * State of a known {@code init} service. 37088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 38088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public enum State { 39088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey RUNNING("running"), 40088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey STOPPING("stopping"), 41088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey STOPPED("stopped"), 42088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey RESTARTING("restarting"); 43088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 44088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey State(String state) { 45088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey sStates.put(state, this); 46088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 47088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 48088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 49088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey private static Object sPropertyLock = new Object(); 50088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 51088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey static { 52088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey SystemProperties.addChangeCallback(new Runnable() { 53088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey @Override 54088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public void run() { 55088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey synchronized (sPropertyLock) { 56088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey sPropertyLock.notifyAll(); 57088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 58088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 59088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey }); 60088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 61088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 62088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** Request that the init daemon start a named service. */ 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void start(String name) { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SystemProperties.set("ctl.start", name); 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 66088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 67088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** Request that the init daemon stop a named service. */ 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void stop(String name) { 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SystemProperties.set("ctl.stop", name); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7130d4d57e8ed421a7d910c86c96c5648c899c2c9bWink Saville 7230d4d57e8ed421a7d910c86c96c5648c899c2c9bWink Saville /** Request that the init daemon restart a named service. */ 7330d4d57e8ed421a7d910c86c96c5648c899c2c9bWink Saville public static void restart(String name) { 7430d4d57e8ed421a7d910c86c96c5648c899c2c9bWink Saville SystemProperties.set("ctl.restart", name); 7530d4d57e8ed421a7d910c86c96c5648c899c2c9bWink Saville } 76088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 77088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** 78088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * Return current state of given service. 79088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 80088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public static State getState(String service) { 81088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey final String rawState = SystemProperties.get("init.svc." + service); 82088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey final State state = sStates.get(rawState); 83088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey if (state != null) { 84088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey return state; 85088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } else { 86899223b97c9b0ae56a8211a46600914c0ecfd854Jeff Sharkey return State.STOPPED; 87088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 88088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 89088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 90088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** 91088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * Check if given service is {@link State#STOPPED}. 92088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 93088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public static boolean isStopped(String service) { 94088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey return State.STOPPED.equals(getState(service)); 95088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 96088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 97088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** 98088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * Check if given service is {@link State#RUNNING}. 99088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 100088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public static boolean isRunning(String service) { 101088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey return State.RUNNING.equals(getState(service)); 102088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 103088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 104088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** 105088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * Wait until given service has entered specific state. 106088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 107088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public static void waitForState(String service, State state, long timeoutMillis) 108088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey throws TimeoutException { 109088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey final long endMillis = SystemClock.elapsedRealtime() + timeoutMillis; 110088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey while (true) { 111088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey synchronized (sPropertyLock) { 112088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey final State currentState = getState(service); 113088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey if (state.equals(currentState)) { 114088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey return; 115088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 116088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 117088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey if (SystemClock.elapsedRealtime() >= endMillis) { 118088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey throw new TimeoutException("Service " + service + " currently " + currentState 119088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey + "; waited " + timeoutMillis + "ms for " + state); 120088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 121088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 122088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey try { 123088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey sPropertyLock.wait(timeoutMillis); 124088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } catch (InterruptedException e) { 125088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 126088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 127088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 128088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 129088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 130088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey /** 131088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey * Wait until any of given services enters {@link State#STOPPED}. 132088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey */ 133088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey public static void waitForAnyStopped(String... services) { 134088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey while (true) { 135088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey synchronized (sPropertyLock) { 136088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey for (String service : services) { 137088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey if (State.STOPPED.equals(getState(service))) { 138088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey return; 139088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 140088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 141088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey 142088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey try { 143088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey sPropertyLock.wait(); 144088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } catch (InterruptedException e) { 145088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 146088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 147088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 148088f29f55eebc6862a4cb5dddeaefacf24f74d95Jeff Sharkey } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 150