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

Commit 7aa79efe authored by Erik Kline's avatar Erik Kline
Browse files

Grab a wakelock while doing ARP/ND probing

Bug: 23197666
Change-Id: I5bf6e83b37fcd924f5f8e750f65bb5061f931e56
parent 7bd7a242
Loading
Loading
Loading
Loading
+34 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.net;

import com.android.internal.annotations.GuardedBy;

import android.content.Context;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.LinkProperties.ProvisioningChange;
@@ -31,6 +32,7 @@ import android.net.netlink.RtNetlinkNeighborMessage;
import android.net.netlink.StructNdaCacheInfo;
import android.net.netlink.StructNdMsg;
import android.net.netlink.StructNlMsgHdr;
import android.os.PowerManager;
import android.os.SystemClock;
import android.system.ErrnoException;
import android.system.NetlinkSocketAddress;
@@ -74,6 +76,7 @@ public class IpReachabilityMonitor {
    }

    private final Object mLock = new Object();
    private final PowerManager.WakeLock mWakeLock;
    private final String mInterfaceName;
    private final int mInterfaceIndex;
    private final Callback mCallback;
@@ -136,7 +139,8 @@ public class IpReachabilityMonitor {
        return returnValue;
    }

    public IpReachabilityMonitor(String ifName, Callback callback) throws IllegalArgumentException {
    public IpReachabilityMonitor(Context context, String ifName, Callback callback)
                throws IllegalArgumentException {
        mInterfaceName = ifName;
        int ifIndex = -1;
        try {
@@ -145,6 +149,8 @@ public class IpReachabilityMonitor {
        } catch (SocketException | NullPointerException e) {
            throw new IllegalArgumentException("invalid interface '" + ifName + "': ", e);
        }
        mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock(
                PowerManager.PARTIAL_WAKE_LOCK, TAG + "." + mInterfaceName);
        mCallback = callback;
        mNetlinkSocketObserver = new NetlinkSocketObserver();
        mObserverThread = new Thread(mNetlinkSocketObserver);
@@ -291,6 +297,17 @@ public class IpReachabilityMonitor {
        synchronized (mLock) {
            ipProbeList.addAll(mIpWatchList.keySet());
        }

        if (!ipProbeList.isEmpty() && stillRunning()) {
            // Keep the CPU awake long enough to allow all ARP/ND
            // probes a reasonable chance at success. See b/23197666.
            //
            // The wakelock we use is (by default) refcounted, and this version
            // of acquire(timeout) queues a release message to keep acquisitions
            // and releases balanced.
            mWakeLock.acquire(getProbeWakeLockDuration());
        }

        for (InetAddress target : ipProbeList) {
            if (!stillRunning()) {
                break;
@@ -299,6 +316,22 @@ public class IpReachabilityMonitor {
        }
    }

    private long getProbeWakeLockDuration() {
        // Ideally, this would be computed by examining the values of:
        //
        //     /proc/sys/net/ipv[46]/neigh/<ifname>/ucast_solicit
        //
        // and:
        //
        //     /proc/sys/net/ipv[46]/neigh/<ifname>/retrans_time_ms
        //
        // For now, just make some assumptions.
        final long numUnicastProbes = 3;
        final long retransTimeMs = 1000;
        final long gracePeriodMs = 500;
        return (numUnicastProbes * retransTimeMs) + gracePeriodMs;
    }


    // TODO: simply the number of objects by making this extend Thread.
    private final class NetlinkSocketObserver implements Runnable {