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

Commit b331b02d authored by Erik Kline's avatar Erik Kline Committed by Gerrit Code Review
Browse files

Merge "Fail if the interface is not available when starting"

parents 0b8d55e6 b152cd0a
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -40,11 +40,12 @@ public final class IpManagerEvent implements Parcelable {
    public static final int ERROR_STARTING_IPV6                   = 5;
    public static final int ERROR_STARTING_IPV6                   = 5;
    public static final int ERROR_STARTING_IPREACHABILITYMONITOR  = 6;
    public static final int ERROR_STARTING_IPREACHABILITYMONITOR  = 6;
    public static final int ERROR_INVALID_PROVISIONING            = 7;
    public static final int ERROR_INVALID_PROVISIONING            = 7;
    public static final int ERROR_INTERFACE_NOT_FOUND             = 8;


    @IntDef(value = {
    @IntDef(value = {
            PROVISIONING_OK, PROVISIONING_FAIL, COMPLETE_LIFECYCLE,
            PROVISIONING_OK, PROVISIONING_FAIL, COMPLETE_LIFECYCLE,
            ERROR_STARTING_IPV4, ERROR_STARTING_IPV6, ERROR_STARTING_IPREACHABILITYMONITOR,
            ERROR_STARTING_IPV4, ERROR_STARTING_IPV6, ERROR_STARTING_IPREACHABILITYMONITOR,
            ERROR_INVALID_PROVISIONING,
            ERROR_INVALID_PROVISIONING, ERROR_INTERFACE_NOT_FOUND,
    })
    })
    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
    public @interface EventType {}
    public @interface EventType {}
+40 −13
Original line number Original line Diff line number Diff line
@@ -540,6 +540,8 @@ public class IpClient extends StateMachine {
    // TODO: Revert this hack once IpClient and Nat464Xlat work in concert.
    // TODO: Revert this hack once IpClient and Nat464Xlat work in concert.
    private static final String CLAT_PREFIX = "v4-";
    private static final String CLAT_PREFIX = "v4-";


    private static final int IMMEDIATE_FAILURE_DURATION = 0;

    private final State mStoppedState = new StoppedState();
    private final State mStoppedState = new StoppedState();
    private final State mStoppingState = new StoppingState();
    private final State mStoppingState = new StoppingState();
    private final State mStartedState = new StartedState();
    private final State mStartedState = new StartedState();
@@ -551,6 +553,7 @@ public class IpClient extends StateMachine {
    private final String mClatInterfaceName;
    private final String mClatInterfaceName;
    @VisibleForTesting
    @VisibleForTesting
    protected final Callback mCallback;
    protected final Callback mCallback;
    private final Dependencies mDependencies;
    private final CountDownLatch mShutdownLatch;
    private final CountDownLatch mShutdownLatch;
    private final INetworkManagementService mNwService;
    private final INetworkManagementService mNwService;
    private final NetlinkTracker mNetlinkTracker;
    private final NetlinkTracker mNetlinkTracker;
@@ -579,10 +582,23 @@ public class IpClient extends StateMachine {
    private boolean mMulticastFiltering;
    private boolean mMulticastFiltering;
    private long mStartTimeMillis;
    private long mStartTimeMillis;


    public static class Dependencies {
        public INetworkManagementService getNMS() {
            return INetworkManagementService.Stub.asInterface(
                    ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
        }

        public INetd getNetd() {
            return NetdService.getInstance();
        }

        public InterfaceParams getInterfaceParams(String ifname) {
            return InterfaceParams.getByName(ifname);
        }
    }

    public IpClient(Context context, String ifName, Callback callback) {
    public IpClient(Context context, String ifName, Callback callback) {
        this(context, ifName, callback, INetworkManagementService.Stub.asInterface(
        this(context, ifName, callback, new Dependencies());
                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)),
                NetdService.getInstance());
    }
    }


    /**
    /**
@@ -591,27 +607,35 @@ public class IpClient extends StateMachine {
     */
     */
    public IpClient(Context context, String ifName, Callback callback,
    public IpClient(Context context, String ifName, Callback callback,
            INetworkManagementService nwService) {
            INetworkManagementService nwService) {
        this(context, ifName, callback, nwService, NetdService.getInstance());
        this(context, ifName, callback, new Dependencies() {
            @Override
            public INetworkManagementService getNMS() { return nwService; }
        });
    }
    }


    @VisibleForTesting
    @VisibleForTesting
    IpClient(Context context, String ifName, Callback callback,
    IpClient(Context context, String ifName, Callback callback, Dependencies deps) {
            INetworkManagementService nwService, INetd netd) {
        super(IpClient.class.getSimpleName() + "." + ifName);
        super(IpClient.class.getSimpleName() + "." + ifName);
        Preconditions.checkNotNull(ifName);
        Preconditions.checkNotNull(callback);

        mTag = getName();
        mTag = getName();


        mContext = context;
        mContext = context;
        mInterfaceName = ifName;
        mInterfaceName = ifName;
        mClatInterfaceName = CLAT_PREFIX + ifName;
        mClatInterfaceName = CLAT_PREFIX + ifName;
        mCallback = new LoggingCallbackWrapper(callback);
        mCallback = new LoggingCallbackWrapper(callback);
        mDependencies = deps;
        mShutdownLatch = new CountDownLatch(1);
        mShutdownLatch = new CountDownLatch(1);
        mNwService = nwService;
        mNwService = deps.getNMS();


        mLog = new SharedLog(MAX_LOG_RECORDS, mTag);
        mLog = new SharedLog(MAX_LOG_RECORDS, mTag);
        mConnectivityPacketLog = new LocalLog(MAX_PACKET_RECORDS);
        mConnectivityPacketLog = new LocalLog(MAX_PACKET_RECORDS);
        mMsgStateLogger = new MessageHandlingLogger();
        mMsgStateLogger = new MessageHandlingLogger();


        mInterfaceCtrl = new InterfaceController(mInterfaceName, mNwService, netd, mLog);
        // TODO: Consider creating, constructing, and passing in some kind of
        // InterfaceController.Dependencies class.
        mInterfaceCtrl = new InterfaceController(mInterfaceName, mNwService, deps.getNetd(), mLog);


        mNetlinkTracker = new NetlinkTracker(
        mNetlinkTracker = new NetlinkTracker(
                mInterfaceName,
                mInterfaceName,
@@ -742,11 +766,11 @@ public class IpClient extends StateMachine {
            return;
            return;
        }
        }


        mInterfaceParams = InterfaceParams.getByName(mInterfaceName);
        mInterfaceParams = mDependencies.getInterfaceParams(mInterfaceName);
        if (mInterfaceParams == null) {
        if (mInterfaceParams == null) {
            logError("Failed to find InterfaceParams for " + mInterfaceName);
            logError("Failed to find InterfaceParams for " + mInterfaceName);
            // TODO: call doImmediateProvisioningFailure() with an error code
            doImmediateProvisioningFailure(IpManagerEvent.ERROR_INTERFACE_NOT_FOUND);
            // indicating something like "interface not ready".
            return;
        }
        }


        mCallback.setNeighborDiscoveryOffload(true);
        mCallback.setNeighborDiscoveryOffload(true);
@@ -930,8 +954,11 @@ public class IpClient extends StateMachine {
    }
    }


    private void recordMetric(final int type) {
    private void recordMetric(final int type) {
        if (mStartTimeMillis <= 0) { Log.wtf(mTag, "Start time undefined!"); }
        // We may record error metrics prior to starting.
        final long duration = SystemClock.elapsedRealtime() - mStartTimeMillis;
        // Map this to IMMEDIATE_FAILURE_DURATION.
        final long duration = (mStartTimeMillis > 0)
                ? (SystemClock.elapsedRealtime() - mStartTimeMillis)
                : IMMEDIATE_FAILURE_DURATION;
        mMetricsLog.log(mInterfaceName, new IpManagerEvent(type, duration));
        mMetricsLog.log(mInterfaceName, new IpManagerEvent(type, duration));
    }
    }


+1 −14
Original line number Original line Diff line number Diff line
@@ -144,20 +144,7 @@ public class IpManager extends IpClient {
    }
    }


    public IpManager(Context context, String ifName, Callback callback) {
    public IpManager(Context context, String ifName, Callback callback) {
        this(context, ifName, callback, INetworkManagementService.Stub.asInterface(
        super(context, ifName, callback);
                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)),
                NetdService.getInstance());
    }

    public IpManager(Context context, String ifName, Callback callback,
            INetworkManagementService nwService) {
        this(context, ifName, callback, nwService, NetdService.getInstance());
    }

    @VisibleForTesting
    public IpManager(Context context, String ifName, Callback callback,
            INetworkManagementService nwService, INetd netd) {
        super(context, ifName, callback, nwService, netd);
    }
    }


    public void startProvisioning(ProvisioningConfiguration req) {
    public void startProvisioning(ProvisioningConfiguration req) {
+88 −35
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.never;
@@ -38,10 +39,12 @@ import android.net.INetd;
import android.net.IpPrefix;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.RouteInfo;
import android.net.RouteInfo;
import android.net.ip.IpManager.Callback;
import android.net.ip.IpClient.Callback;
import android.net.ip.IpManager.InitialConfiguration;
import android.net.ip.IpClient.InitialConfiguration;
import android.net.ip.IpManager.ProvisioningConfiguration;
import android.net.ip.IpClient.ProvisioningConfiguration;
import android.net.util.InterfaceParams;
import android.os.INetworkManagementService;
import android.os.INetworkManagementService;
import android.provider.Settings;
import android.provider.Settings;
import android.support.test.filters.SmallTest;
import android.support.test.filters.SmallTest;
@@ -68,15 +71,19 @@ import java.util.HashSet;
import java.util.Set;
import java.util.Set;


/**
/**
 * Tests for IpManager.
 * Tests for IpClient.
 */
 */
@RunWith(AndroidJUnit4.class)
@RunWith(AndroidJUnit4.class)
@SmallTest
@SmallTest
public class IpManagerTest {
public class IpClientTest {
    private static final int DEFAULT_AVOIDBADWIFI_CONFIG_VALUE = 1;
    private static final int DEFAULT_AVOIDBADWIFI_CONFIG_VALUE = 1;


    private static final String VALID = "VALID";
    private static final String VALID = "VALID";
    private static final String INVALID = "INVALID";
    private static final String INVALID = "INVALID";
    private static final String TEST_IFNAME = "test_wlan0";
    private static final int TEST_IFINDEX = 1001;
    // See RFC 7042#section-2.1.2 for EUI-48 documentation values.
    private static final MacAddress TEST_MAC = MacAddress.fromString("00:00:5E:00:53:01");


    @Mock private Context mContext;
    @Mock private Context mContext;
    @Mock private INetworkManagementService mNMService;
    @Mock private INetworkManagementService mNMService;
@@ -84,9 +91,11 @@ public class IpManagerTest {
    @Mock private Resources mResources;
    @Mock private Resources mResources;
    @Mock private Callback mCb;
    @Mock private Callback mCb;
    @Mock private AlarmManager mAlarm;
    @Mock private AlarmManager mAlarm;
    @Mock private IpClient.Dependencies mDependecies;
    private MockContentResolver mContentResolver;
    private MockContentResolver mContentResolver;


    BaseNetworkObserver mObserver;
    private BaseNetworkObserver mObserver;
    private InterfaceParams mIfParams;


    @Before
    @Before
    public void setUp() throws Exception {
    public void setUp() throws Exception {
@@ -100,10 +109,23 @@ public class IpManagerTest {
        mContentResolver = new MockContentResolver();
        mContentResolver = new MockContentResolver();
        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
        when(mContext.getContentResolver()).thenReturn(mContentResolver);
        when(mContext.getContentResolver()).thenReturn(mContentResolver);

        mIfParams = null;

        when(mDependecies.getNMS()).thenReturn(mNMService);
        when(mDependecies.getNetd()).thenReturn(mNetd);
    }

    private void setTestInterfaceParams(String ifname) {
        mIfParams = (ifname != null)
                ? new InterfaceParams(ifname, TEST_IFINDEX, TEST_MAC)
                : null;
        when(mDependecies.getInterfaceParams(anyString())).thenReturn(mIfParams);
    }
    }


    private IpManager makeIpManager(String ifname) throws Exception {
    private IpClient makeIpClient(String ifname) throws Exception {
        final IpManager ipm = new IpManager(mContext, ifname, mCb, mNMService, mNetd);
        setTestInterfaceParams(ifname);
        final IpClient ipc = new IpClient(mContext, ifname, mCb, mDependecies);
        verify(mNMService, timeout(100).times(1)).disableIpv6(ifname);
        verify(mNMService, timeout(100).times(1)).disableIpv6(ifname);
        verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(ifname);
        verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(ifname);
        ArgumentCaptor<BaseNetworkObserver> arg =
        ArgumentCaptor<BaseNetworkObserver> arg =
@@ -111,23 +133,54 @@ public class IpManagerTest {
        verify(mNMService, times(1)).registerObserver(arg.capture());
        verify(mNMService, times(1)).registerObserver(arg.capture());
        mObserver = arg.getValue();
        mObserver = arg.getValue();
        reset(mNMService);
        reset(mNMService);
        return ipm;
        return ipc;
    }

    @Test
    public void testNullInterfaceNameMostDefinitelyThrows() throws Exception {
        setTestInterfaceParams(null);
        try {
            final IpClient ipc = new IpClient(mContext, null, mCb, mDependecies);
            ipc.shutdown();
            fail();
        } catch (NullPointerException npe) {
            // Phew; null interface names not allowed.
        }
    }
    }


    @Test
    @Test
    public void testNullCallbackDoesNotThrow() throws Exception {
    public void testNullCallbackMostDefinitelyThrows() throws Exception {
        final IpManager ipm = new IpManager(mContext, "lo", null, mNMService);
        final String ifname = "lo";
        setTestInterfaceParams(ifname);
        try {
            final IpClient ipc = new IpClient(mContext, ifname, null, mDependecies);
            ipc.shutdown();
            fail();
        } catch (NullPointerException npe) {
            // Phew; null callbacks not allowed.
        }
    }
    }


    @Test
    @Test
    public void testInvalidInterfaceDoesNotThrow() throws Exception {
    public void testInvalidInterfaceDoesNotThrow() throws Exception {
        final IpManager ipm = new IpManager(mContext, "test_wlan0", mCb, mNMService);
        setTestInterfaceParams(TEST_IFNAME);
        final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mDependecies);
        ipc.shutdown();
    }

    @Test
    public void testInterfaceNotFoundFailsImmediately() throws Exception {
        setTestInterfaceParams(null);
        final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mDependecies);
        ipc.startProvisioning(new IpClient.ProvisioningConfiguration());
        verify(mCb, times(1)).onProvisioningFailure(any());
        ipc.shutdown();
    }
    }


    @Test
    @Test
    public void testDefaultProvisioningConfiguration() throws Exception {
    public void testDefaultProvisioningConfiguration() throws Exception {
        final String iface = "test_wlan0";
        final String iface = TEST_IFNAME;
        final IpManager ipm = makeIpManager(iface);
        final IpClient ipc = makeIpClient(iface);


        ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
        ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
                .withoutIPv4()
                .withoutIPv4()
@@ -136,20 +189,20 @@ public class IpManagerTest {
                .withoutIpReachabilityMonitor()
                .withoutIpReachabilityMonitor()
                .build();
                .build();


        ipm.startProvisioning(config);
        ipc.startProvisioning(config);
        verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
        verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
        verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false);
        verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false);
        verify(mCb, never()).onProvisioningFailure(any());
        verify(mCb, never()).onProvisioningFailure(any());


        ipm.stop();
        ipc.shutdown();
        verify(mNMService, timeout(100).times(1)).disableIpv6(iface);
        verify(mNMService, timeout(100).times(1)).disableIpv6(iface);
        verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface);
        verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface);
    }
    }


    @Test
    @Test
    public void testProvisioningWithInitialConfiguration() throws Exception {
    public void testProvisioningWithInitialConfiguration() throws Exception {
        final String iface = "test_wlan0";
        final String iface = TEST_IFNAME;
        final IpManager ipm = makeIpManager(iface);
        final IpClient ipc = makeIpClient(iface);


        String[] addresses = {
        String[] addresses = {
            "fe80::a4be:f92:e1f7:22d1/64",
            "fe80::a4be:f92:e1f7:22d1/64",
@@ -164,7 +217,7 @@ public class IpManagerTest {
                .withInitialConfiguration(conf(links(addresses), prefixes(prefixes), ips()))
                .withInitialConfiguration(conf(links(addresses), prefixes(prefixes), ips()))
                .build();
                .build();


        ipm.startProvisioning(config);
        ipc.startProvisioning(config);
        verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
        verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
        verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false);
        verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false);
        verify(mCb, never()).onProvisioningFailure(any());
        verify(mCb, never()).onProvisioningFailure(any());
@@ -190,7 +243,7 @@ public class IpManagerTest {
        want.setInterfaceName(iface);
        want.setInterfaceName(iface);
        verify(mCb, timeout(100).times(1)).onProvisioningSuccess(eq(want));
        verify(mCb, timeout(100).times(1)).onProvisioningSuccess(eq(want));


        ipm.stop();
        ipc.shutdown();
        verify(mNMService, timeout(100).times(1)).disableIpv6(iface);
        verify(mNMService, timeout(100).times(1)).disableIpv6(iface);
        verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface);
        verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface);
    }
    }
@@ -228,7 +281,7 @@ public class IpManagerTest {
        };
        };


        for (IsProvisionedTestCase testcase : testcases) {
        for (IsProvisionedTestCase testcase : testcases) {
            if (IpManager.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) {
            if (IpClient.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) {
                fail(testcase.errorMessage());
                fail(testcase.errorMessage());
            }
            }
        }
        }
@@ -424,11 +477,11 @@ public class IpManagerTest {
        List<String> list3 = Arrays.asList("bar", "baz");
        List<String> list3 = Arrays.asList("bar", "baz");
        List<String> list4 = Arrays.asList("foo", "bar", "baz");
        List<String> list4 = Arrays.asList("foo", "bar", "baz");


        assertTrue(IpManager.all(list1, (x) -> false));
        assertTrue(IpClient.all(list1, (x) -> false));
        assertFalse(IpManager.all(list2, (x) -> false));
        assertFalse(IpClient.all(list2, (x) -> false));
        assertTrue(IpManager.all(list3, (x) -> true));
        assertTrue(IpClient.all(list3, (x) -> true));
        assertTrue(IpManager.all(list2, (x) -> x.charAt(0) == 'f'));
        assertTrue(IpClient.all(list2, (x) -> x.charAt(0) == 'f'));
        assertFalse(IpManager.all(list4, (x) -> x.charAt(0) == 'f'));
        assertFalse(IpClient.all(list4, (x) -> x.charAt(0) == 'f'));
    }
    }


    @Test
    @Test
@@ -438,11 +491,11 @@ public class IpManagerTest {
        List<String> list3 = Arrays.asList("bar", "baz");
        List<String> list3 = Arrays.asList("bar", "baz");
        List<String> list4 = Arrays.asList("foo", "bar", "baz");
        List<String> list4 = Arrays.asList("foo", "bar", "baz");


        assertFalse(IpManager.any(list1, (x) -> true));
        assertFalse(IpClient.any(list1, (x) -> true));
        assertTrue(IpManager.any(list2, (x) -> true));
        assertTrue(IpClient.any(list2, (x) -> true));
        assertTrue(IpManager.any(list2, (x) -> x.charAt(0) == 'f'));
        assertTrue(IpClient.any(list2, (x) -> x.charAt(0) == 'f'));
        assertFalse(IpManager.any(list3, (x) -> x.charAt(0) == 'f'));
        assertFalse(IpClient.any(list3, (x) -> x.charAt(0) == 'f'));
        assertTrue(IpManager.any(list4, (x) -> x.charAt(0) == 'f'));
        assertTrue(IpClient.any(list4, (x) -> x.charAt(0) == 'f'));
    }
    }


    @Test
    @Test
@@ -451,9 +504,9 @@ public class IpManagerTest {
        List<String> list2 = Arrays.asList("foo");
        List<String> list2 = Arrays.asList("foo");
        List<String> list3 = Arrays.asList("foo", "bar", "baz");
        List<String> list3 = Arrays.asList("foo", "bar", "baz");


        assertEquals(list1, IpManager.findAll(list1, (x) -> true));
        assertEquals(list1, IpClient.findAll(list1, (x) -> true));
        assertEquals(list1, IpManager.findAll(list3, (x) -> false));
        assertEquals(list1, IpClient.findAll(list3, (x) -> false));
        assertEquals(list3, IpManager.findAll(list3, (x) -> true));
        assertEquals(list3, IpClient.findAll(list3, (x) -> true));
        assertEquals(list2, IpManager.findAll(list3, (x) -> x.charAt(0) == 'f'));
        assertEquals(list2, IpClient.findAll(list3, (x) -> x.charAt(0) == 'f'));
    }
    }
}
}