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

Commit ba8c613e authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add blocking and retrying wrappers for INetd uses."

parents e3ece71f af39244a
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);
            }
        }
    }
}