Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 82f479d0 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Cleaner controls between Vpn and init services." into jb-mr1-dev

parents f3c16a12 088f29f5
Loading
Loading
Loading
Loading
+117 −6
Original line number Diff line number Diff line
@@ -16,9 +16,47 @@

package android.os;

/** @hide */
public class SystemService
{
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);
@@ -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) {
                }
            }
        }
    }
}
+6 −10
Original line number Diff line number Diff line
@@ -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);
                    }
                }