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

Commit b7a55f4a authored by Erik Kline's avatar Erik Kline Committed by android-build-merger
Browse files

Merge "Add blocking and retrying wrappers for INetd uses." am: ba8c613e am: 143d0853

am: 300c56a9

Change-Id: Ia9d45d8fd636e918c8299b26163de0650f8ddac5
parents 44d5d0c2 300c56a9
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.Context;
import android.net.apf.ApfCapabilities;
import android.net.apf.ApfFilter;
import android.net.DhcpResults;
import android.net.INetd;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -34,10 +35,12 @@ import android.net.dhcp.DhcpClient;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpManagerEvent;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.NetdService;
import android.os.INetworkManagementService;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.LocalLog;
@@ -1027,14 +1030,16 @@ public class IpManager extends StateMachine {

    private boolean startIPv6() {
        // Set privacy extensions.
        final String PREFER_TEMPADDRS = "2";
        try {
            mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
            NetdService.run((INetd netd) -> {
                netd.setProcSysNet(
                        INetd.IPV6, INetd.CONF, mInterfaceName, "use_tempaddr",
                        PREFER_TEMPADDRS);
            });
            mNwService.enableIpv6(mInterfaceName);
        } catch (RemoteException re) {
            logError("Unable to change interface settings: %s", re);
            return false;
        } catch (IllegalStateException ie) {
            logError("Unable to change interface settings: %s", ie);
        } catch (IllegalStateException|RemoteException|ServiceSpecificException e) {
            logError("Unable to change interface settings: %s", e);
            return false;
        }

+90 −0
Original line number Diff line number Diff line
@@ -17,7 +17,10 @@
package android.net.util;

import android.net.INetd;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.util.Log;


@@ -27,15 +30,24 @@ import android.util.Log;
public class NetdService {
    private static final String TAG = NetdService.class.getSimpleName();
    private static final String NETD_SERVICE_NAME = "netd";
    private static final long BASE_TIMEOUT_MS = 100;
    private static final long MAX_TIMEOUT_MS = 1000;


    /**
     * Return an INetd instance, or null if not available.
     *
     * It is the caller's responsibility to check for a null return value
     * and to handle RemoteException errors from invocations on the returned
     * interface if, for example, netd dies and is restarted.
     *
     * Returned instances of INetd should not be cached.
     *
     * @return an INetd instance or null.
     */
    public static INetd getInstance() {
        // NOTE: ServiceManager does no caching for the netd service,
        // because netd is not one of the defined common services.
        final INetd netdInstance = INetd.Stub.asInterface(
                ServiceManager.getService(NETD_SERVICE_NAME));
        if (netdInstance == null) {
@@ -43,4 +55,82 @@ public class NetdService {
        }
        return netdInstance;
    }

    /**
     * Blocks for a specified time until an INetd instance is available.
     *
     * It is the caller's responsibility to handle RemoteException errors
     * from invocations on the returned interface if, for example, netd
     * dies after this interface was returned.
     *
     * Returned instances of INetd should not be cached.
     *
     * Special values of maxTimeoutMs include: 0, meaning try to obtain an
     * INetd instance only once, and -1 (or any value less than 0), meaning
     * try to obtain an INetd instance indefinitely.
     *
     * @param maxTimeoutMs the maximum time to spend getting an INetd instance
     * @return an INetd instance or null if no instance is available
     * within |maxTimeoutMs| milliseconds.
     */
    public static INetd get(long maxTimeoutMs) {
        if (maxTimeoutMs == 0) return getInstance();

        final long stop = (maxTimeoutMs > 0)
                ? SystemClock.elapsedRealtime() + maxTimeoutMs
                : Long.MAX_VALUE;

        long timeoutMs = 0;
        while (true) {
            final INetd netdInstance = getInstance();
            if (netdInstance != null) {
                return netdInstance;
            }

            final long remaining = stop - SystemClock.elapsedRealtime();
            if (remaining <= 0) break;

            // No netdInstance was received; sleep and retry.
            timeoutMs = Math.min(timeoutMs + BASE_TIMEOUT_MS, MAX_TIMEOUT_MS);
            timeoutMs = Math.min(timeoutMs, remaining);
            try {
                Thread.sleep(timeoutMs);
            } catch (InterruptedException e) {}
        }
        return null;
    }

    /**
     * Blocks until an INetd instance is available.
     *
     * It is the caller's responsibility to handle RemoteException errors
     * from invocations on the returned interface if, for example, netd
     * dies after this interface was returned.
     *
     * Returned instances of INetd should not be cached.
     *
     * @return an INetd instance.
     */
    public static INetd get() {
        return get(-1);
    }

    public static interface NetdCommand {
        void run(INetd netd) throws RemoteException;
    }

    /**
     * Blocks until an INetd instance is availabe, and retries until either
     * the command succeeds or a runtime exception is thrown.
     */
    public static void run(NetdCommand cmd) {
        while (true) {
            try {
                cmd.run(get());
                return;
            } catch (RemoteException re) {
                Log.e(TAG, "error communicating with netd: " + re);
            }
        }
    }
}