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

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

Merge "Support setting upstream parameters." am: faf8d677 am: 4e502413 am: e2018a40

am: 6ce08f62

Change-Id: Ia290ef28f466d6a5c3f7208b1bc078bd7a2c204a
parents 7c68a15c 6ce08f62
Loading
Loading
Loading
Loading
+47 −2
Original line number Original line Diff line number Diff line
@@ -20,10 +20,15 @@ import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;


import android.content.ContentResolver;
import android.content.ContentResolver;
import android.net.LinkProperties;
import android.net.LinkProperties;
import android.net.RouteInfo;
import android.net.util.SharedLog;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.Handler;
import android.provider.Settings;
import android.provider.Settings;


import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;

/**
/**
 * A class to encapsulate the business logic of programming the tethering
 * A class to encapsulate the business logic of programming the tethering
 * hardware offload interface.
 * hardware offload interface.
@@ -92,8 +97,12 @@ public class OffloadController {
    public void setUpstreamLinkProperties(LinkProperties lp) {
    public void setUpstreamLinkProperties(LinkProperties lp) {
        if (!started()) return;
        if (!started()) return;


        // TODO: setUpstreamParameters().
        mUpstreamLinkProperties = (lp != null) ? new LinkProperties(lp) : null;
        mUpstreamLinkProperties = lp;
        // TODO: examine return code and decide what to do if programming
        // upstream parameters fails (probably just wait for a subsequent
        // onOffloadEvent() callback to tell us offload is available again and
        // then reapply all state).
        pushUpstreamParameters();
    }
    }


    // TODO: public void addDownStream(...)
    // TODO: public void addDownStream(...)
@@ -106,4 +115,40 @@ public class OffloadController {
    private boolean started() {
    private boolean started() {
        return mConfigInitialized && mControlInitialized;
        return mConfigInitialized && mControlInitialized;
    }
    }

    private boolean pushUpstreamParameters() {
        if (mUpstreamLinkProperties == null) {
            return mHwInterface.setUpstreamParameters(null, null, null, null);
        }

        // A stacked interface cannot be an upstream for hardware offload.
        // Consequently, we examine only the primary interface name, look at
        // getAddresses() rather than getAllAddresses(), and check getRoutes()
        // rather than getAllRoutes().
        final String iface = mUpstreamLinkProperties.getInterfaceName();
        final ArrayList<String> v6gateways = new ArrayList<>();
        String v4addr = null;
        String v4gateway = null;

        for (InetAddress ip : mUpstreamLinkProperties.getAddresses()) {
            if (ip instanceof Inet4Address) {
                v4addr = ip.getHostAddress();
                break;
            }
        }

        // Find the gateway addresses of all default routes of either address family.
        for (RouteInfo ri : mUpstreamLinkProperties.getRoutes()) {
            if (!ri.hasGateway()) continue;

            final String gateway = ri.getGateway().getHostAddress();
            if (ri.isIPv4Default()) {
                v4gateway = gateway;
            } else if (ri.isIPv6Default()) {
                v6gateways.add(gateway);
            }
        }

        return mHwInterface.setUpstreamParameters(iface, v4addr, v4gateway, v6gateways);
    }
}
}
+21 −0
Original line number Original line Diff line number Diff line
@@ -23,6 +23,8 @@ import android.os.Handler;
import android.os.RemoteException;
import android.os.RemoteException;
import android.net.util.SharedLog;
import android.net.util.SharedLog;


import java.util.ArrayList;



/**
/**
 * Capture tethering dependencies, for injection.
 * Capture tethering dependencies, for injection.
@@ -103,6 +105,25 @@ public class OffloadHardwareInterface {
        mControlCallback = null;
        mControlCallback = null;
    }
    }


    public boolean setUpstreamParameters(
            String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) {
        final CbResults results = new CbResults();
        try {
            mOffloadControl.setUpstreamParameters(
                    iface, v4addr, v4gateway, v6gws,
                    (boolean success, String errMsg) -> {
                        results.success = success;
                        results.errMsg = errMsg;
                    });
        } catch (RemoteException e) {
            mLog.e("failed to setUpstreamParameters: " + e);
            return false;
        }

        if (!results.success) mLog.e("setUpstreamParameters failed: " + results.errMsg);
        return results.success;
    }

    private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub {
    private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub {
        public final Handler handler;
        public final Handler handler;
        public final ControlCallback controlCb;
        public final ControlCallback controlCb;
+95 −0
Original line number Original line Diff line number Diff line
@@ -17,15 +17,22 @@
package com.android.server.connectivity.tethering;
package com.android.server.connectivity.tethering;


import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.when;


import android.content.Context;
import android.content.Context;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.RouteInfo;
import android.net.util.SharedLog;
import android.net.util.SharedLog;
import android.provider.Settings;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.provider.Settings.SettingNotFoundException;
@@ -35,9 +42,13 @@ import android.support.test.runner.AndroidJUnit4;
import android.test.mock.MockContentResolver;
import android.test.mock.MockContentResolver;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProvider;


import java.net.InetAddress;
import java.util.ArrayList;

import org.junit.Before;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;
import org.junit.Test;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations;
@@ -49,6 +60,7 @@ public class OffloadControllerTest {


    @Mock private OffloadHardwareInterface mHardware;
    @Mock private OffloadHardwareInterface mHardware;
    @Mock private Context mContext;
    @Mock private Context mContext;
    final ArgumentCaptor<ArrayList> mStringArrayCaptor = ArgumentCaptor.forClass(ArrayList.class);
    private MockContentResolver mContentResolver;
    private MockContentResolver mContentResolver;


    @Before public void setUp() throws Exception {
    @Before public void setUp() throws Exception {
@@ -114,4 +126,87 @@ public class OffloadControllerTest {
        inOrder.verify(mHardware, never()).initOffloadControl(anyObject());
        inOrder.verify(mHardware, never()).initOffloadControl(anyObject());
        inOrder.verifyNoMoreInteractions();
        inOrder.verifyNoMoreInteractions();
    }
    }

    @Test
    public void testSetUpstreamLinkPropertiesWorking() throws Exception {
        setupFunctioningHardwareInterface();
        final OffloadController offload =
                new OffloadController(null, mHardware, mContentResolver, new SharedLog("test"));
        offload.start();

        final InOrder inOrder = inOrder(mHardware);
        inOrder.verify(mHardware, times(1)).initOffloadConfig();
        inOrder.verify(mHardware, times(1)).initOffloadControl(
                any(OffloadHardwareInterface.ControlCallback.class));
        inOrder.verifyNoMoreInteractions();

        offload.setUpstreamLinkProperties(null);
        inOrder.verify(mHardware, times(1)).setUpstreamParameters(
                eq(null), eq(null), eq(null), eq(null));
        inOrder.verifyNoMoreInteractions();
        reset(mHardware);

        final LinkProperties lp = new LinkProperties();

        final String testIfName = "rmnet_data17";
        lp.setInterfaceName(testIfName);
        offload.setUpstreamLinkProperties(lp);
        inOrder.verify(mHardware, times(1)).setUpstreamParameters(
                eq(testIfName), eq(null), eq(null), mStringArrayCaptor.capture());
        assertTrue(mStringArrayCaptor.getValue().isEmpty());
        inOrder.verifyNoMoreInteractions();

        final String ipv4Addr = "192.0.2.5";
        final String linkAddr = ipv4Addr + "/24";
        lp.addLinkAddress(new LinkAddress(linkAddr));
        offload.setUpstreamLinkProperties(lp);
        inOrder.verify(mHardware, times(1)).setUpstreamParameters(
                eq(testIfName), eq(ipv4Addr), eq(null), mStringArrayCaptor.capture());
        assertTrue(mStringArrayCaptor.getValue().isEmpty());
        inOrder.verifyNoMoreInteractions();

        final String ipv4Gateway = "192.0.2.1";
        lp.addRoute(new RouteInfo(InetAddress.getByName(ipv4Gateway)));
        offload.setUpstreamLinkProperties(lp);
        inOrder.verify(mHardware, times(1)).setUpstreamParameters(
                eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture());
        assertTrue(mStringArrayCaptor.getValue().isEmpty());
        inOrder.verifyNoMoreInteractions();

        final String ipv6Gw1 = "fe80::cafe";
        lp.addRoute(new RouteInfo(InetAddress.getByName(ipv6Gw1)));
        offload.setUpstreamLinkProperties(lp);
        inOrder.verify(mHardware, times(1)).setUpstreamParameters(
                eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture());
        ArrayList<String> v6gws = mStringArrayCaptor.getValue();
        assertEquals(1, v6gws.size());
        assertTrue(v6gws.contains(ipv6Gw1));
        inOrder.verifyNoMoreInteractions();

        final String ipv6Gw2 = "fe80::d00d";
        lp.addRoute(new RouteInfo(InetAddress.getByName(ipv6Gw2)));
        offload.setUpstreamLinkProperties(lp);
        inOrder.verify(mHardware, times(1)).setUpstreamParameters(
                eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture());
        v6gws = mStringArrayCaptor.getValue();
        assertEquals(2, v6gws.size());
        assertTrue(v6gws.contains(ipv6Gw1));
        assertTrue(v6gws.contains(ipv6Gw2));
        inOrder.verifyNoMoreInteractions();

        final LinkProperties stacked = new LinkProperties();
        stacked.setInterfaceName("stacked");
        stacked.addLinkAddress(new LinkAddress("192.0.2.129/25"));
        stacked.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
        stacked.addRoute(new RouteInfo(InetAddress.getByName("fe80::bad:f00")));
        assertTrue(lp.addStackedLink(stacked));
        offload.setUpstreamLinkProperties(lp);
        inOrder.verify(mHardware, times(1)).setUpstreamParameters(
                eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture());
        v6gws = mStringArrayCaptor.getValue();
        assertEquals(2, v6gws.size());
        assertTrue(v6gws.contains(ipv6Gw1));
        assertTrue(v6gws.contains(ipv6Gw2));
        inOrder.verifyNoMoreInteractions();
    }
}
}