am 82f479d0: Merge "Cleaner controls between Vpn and init services." into jb-mr1-dev

* commit '82f479d0647855148af84fe2ba5484cb188c92cc':
  Cleaner controls between Vpn and init services.
This commit is contained in:
Jeff Sharkey
2012-08-08 16:23:59 -07:00
committed by Android Git Automerger
2 changed files with 123 additions and 16 deletions

View File

@@ -16,15 +16,53 @@
package android.os;
/** @hide */
public class SystemService
{
/** Request that the init daemon start a named service. */
import com.google.android.collect.Maps;
import java.util.HashMap;
import java.util.concurrent.TimeoutException;
/**
* Controls and utilities for low-level {@code init} services.
*
* @hide
*/
public class SystemService {
private static HashMap<String, State> sStates = Maps.newHashMap();
/**
* State of a known {@code init} service.
*/
public enum State {
RUNNING("running"),
STOPPING("stopping"),
STOPPED("stopped"),
RESTARTING("restarting");
State(String state) {
sStates.put(state, this);
}
}
private static Object sPropertyLock = new Object();
static {
SystemProperties.addChangeCallback(new Runnable() {
@Override
public void run() {
synchronized (sPropertyLock) {
sPropertyLock.notifyAll();
}
}
});
}
/** Request that the init daemon start a named service. */
public static void start(String name) {
SystemProperties.set("ctl.start", name);
}
/** Request that the init daemon stop a named service. */
/** Request that the init daemon stop a named service. */
public static void stop(String name) {
SystemProperties.set("ctl.stop", name);
}
@@ -33,4 +71,77 @@ public class SystemService
public static void restart(String name) {
SystemProperties.set("ctl.restart", name);
}
/**
* Return current state of given service.
*/
public static State getState(String service) {
final String rawState = SystemProperties.get("init.svc." + service);
final State state = sStates.get(rawState);
if (state != null) {
return state;
} else {
throw new IllegalStateException("Service " + service + " in unknown state " + rawState);
}
}
/**
* Check if given service is {@link State#STOPPED}.
*/
public static boolean isStopped(String service) {
return State.STOPPED.equals(getState(service));
}
/**
* Check if given service is {@link State#RUNNING}.
*/
public static boolean isRunning(String service) {
return State.RUNNING.equals(getState(service));
}
/**
* Wait until given service has entered specific state.
*/
public static void waitForState(String service, State state, long timeoutMillis)
throws TimeoutException {
final long endMillis = SystemClock.elapsedRealtime() + timeoutMillis;
while (true) {
synchronized (sPropertyLock) {
final State currentState = getState(service);
if (state.equals(currentState)) {
return;
}
if (SystemClock.elapsedRealtime() >= endMillis) {
throw new TimeoutException("Service " + service + " currently " + currentState
+ "; waited " + timeoutMillis + "ms for " + state);
}
try {
sPropertyLock.wait(timeoutMillis);
} catch (InterruptedException e) {
}
}
}
}
/**
* Wait until any of given services enters {@link State#STOPPED}.
*/
public static void waitForAnyStopped(String... services) {
while (true) {
synchronized (sPropertyLock) {
for (String service : services) {
if (State.STOPPED.equals(getState(service))) {
return;
}
}
try {
sPropertyLock.wait();
} catch (InterruptedException e) {
}
}
}
}
}

View File

@@ -25,7 +25,6 @@ import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
@@ -39,7 +38,7 @@ import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.SystemService;
import android.util.Log;
import com.android.internal.R;
@@ -485,8 +484,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub {
// Wait for the daemons to stop.
for (String daemon : mDaemons) {
String key = "init.svc." + daemon;
while (!"stopped".equals(SystemProperties.get(key, "stopped"))) {
while (!SystemService.isStopped(daemon)) {
checkpoint(true);
}
}
@@ -519,11 +517,10 @@ public class Vpn extends INetworkManagementEventObserver.Stub {
// Start the daemon.
String daemon = mDaemons[i];
SystemProperties.set("ctl.start", daemon);
SystemService.start(daemon);
// Wait for the daemon to start.
String key = "init.svc." + daemon;
while (!"running".equals(SystemProperties.get(key))) {
while (!SystemService.isRunning(daemon)) {
checkpoint(true);
}
@@ -579,8 +576,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub {
// Check if a running daemon is dead.
for (int i = 0; i < mDaemons.length; ++i) {
String daemon = mDaemons[i];
if (mArguments[i] != null && !"running".equals(
SystemProperties.get("init.svc." + daemon))) {
if (mArguments[i] != null && !SystemService.isRunning(daemon)) {
throw new IllegalStateException(daemon + " is dead");
}
}
@@ -647,7 +643,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub {
// Kill the daemons if they fail to stop.
if (mInfo.state == LegacyVpnInfo.STATE_INITIALIZING) {
for (String daemon : mDaemons) {
SystemProperties.set("ctl.stop", daemon);
SystemService.stop(daemon);
}
}