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

Commit 5d0dc453 authored by Remi NGUYEN VAN's avatar Remi NGUYEN VAN
Browse files

Add tests for IPv4 of dual stack tethering.

Also refactoring some Tethering and TetherInterfaceStateMachine calls
to address testability issues.

This is in preparation of other work to have IPv6-only or 464xlat
tethering working.

Test: runtest frameworks-net
Bug: 38218697
Bug: 64382985
Bug: 64976379
Bug: 64995262
Merged-In: I3b91125b1a715690c2cd417b1e937e568c755d9f
Merged-In: I05de77d9b90d147bf1d6ee7f7ee19a049afddfa1
(cherry-pick of aosp I721aca4789ddfbee5a97316aae0b378d79ee2107)

Change-Id: Idfdd1b9cd5419c1f51f0fbb1eba2f36a9c12474b
parent 601861fd
Loading
Loading
Loading
Loading
+8 −6
Original line number Original line Diff line number Diff line
@@ -181,6 +181,7 @@ public class Tethering extends BaseNetworkObserver {
    private final VersionedBroadcastListener mCarrierConfigChange;
    private final VersionedBroadcastListener mCarrierConfigChange;
    // TODO: Delete SimChangeListener; it's obsolete.
    // TODO: Delete SimChangeListener; it's obsolete.
    private final SimChangeListener mSimChange;
    private final SimChangeListener mSimChange;
    private final TetheringDependencies mDeps;


    private volatile TetheringConfiguration mConfig;
    private volatile TetheringConfiguration mConfig;
    private String mCurrentUpstreamIface;
    private String mCurrentUpstreamIface;
@@ -202,12 +203,13 @@ public class Tethering extends BaseNetworkObserver {
        mPolicyManager = policyManager;
        mPolicyManager = policyManager;
        mLooper = looper;
        mLooper = looper;
        mSystemProperties = systemProperties;
        mSystemProperties = systemProperties;
        mDeps = deps;


        mPublicSync = new Object();
        mPublicSync = new Object();


        mTetherStates = new ArrayMap<>();
        mTetherStates = new ArrayMap<>();


        mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
        mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper, deps);
        mTetherMasterSM.start();
        mTetherMasterSM.start();


        final Handler smHandler = mTetherMasterSM.getHandler();
        final Handler smHandler = mTetherMasterSM.getHandler();
@@ -215,8 +217,8 @@ public class Tethering extends BaseNetworkObserver {
                deps.getOffloadHardwareInterface(smHandler, mLog),
                deps.getOffloadHardwareInterface(smHandler, mLog),
                mContext.getContentResolver(), mNMService,
                mContext.getContentResolver(), mNMService,
                mLog);
                mLog);
        mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
        mUpstreamNetworkMonitor = deps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
                mContext, mTetherMasterSM, mLog, TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
                TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
        mForwardedDownstreams = new HashSet<>();
        mForwardedDownstreams = new HashSet<>();


        IntentFilter filter = new IntentFilter();
        IntentFilter filter = new IntentFilter();
@@ -1241,7 +1243,7 @@ public class Tethering extends BaseNetworkObserver {


        private static final int UPSTREAM_SETTLE_TIME_MS     = 10000;
        private static final int UPSTREAM_SETTLE_TIME_MS     = 10000;


        TetherMasterSM(String name, Looper looper) {
        TetherMasterSM(String name, Looper looper, TetheringDependencies deps) {
            super(name, looper);
            super(name, looper);


            mInitialState = new InitialState();
            mInitialState = new InitialState();
@@ -1261,7 +1263,7 @@ public class Tethering extends BaseNetworkObserver {
            addState(mSetDnsForwardersErrorState);
            addState(mSetDnsForwardersErrorState);


            mNotifyList = new ArrayList<>();
            mNotifyList = new ArrayList<>();
            mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList, mLog);
            mIPv6TetheringCoordinator = deps.getIPv6TetheringCoordinator(mNotifyList, mLog);
            mOffload = new OffloadWrapper();
            mOffload = new OffloadWrapper();


            setInitialState(mInitialState);
            setInitialState(mInitialState);
@@ -1997,7 +1999,7 @@ public class Tethering extends BaseNetworkObserver {
        final TetherState tetherState = new TetherState(
        final TetherState tetherState = new TetherState(
                new TetherInterfaceStateMachine(
                new TetherInterfaceStateMachine(
                    iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
                    iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
                    makeControlCallback(iface)));
                    makeControlCallback(iface), mDeps));
        mTetherStates.put(iface, tetherState);
        mTetherStates.put(iface, tetherState);
        tetherState.stateMachine.start();
        tetherState.stateMachine.start();
    }
    }
+8 −7
Original line number Original line Diff line number Diff line
@@ -117,6 +117,8 @@ public class TetherInterfaceStateMachine extends StateMachine {
    private final int mInterfaceType;
    private final int mInterfaceType;
    private final LinkProperties mLinkProperties;
    private final LinkProperties mLinkProperties;


    private final TetheringDependencies mDeps;

    private int mLastError;
    private int mLastError;
    private int mServingMode;
    private int mServingMode;
    private String mMyUpstreamIfaceName;  // may change over time
    private String mMyUpstreamIfaceName;  // may change over time
@@ -134,18 +136,19 @@ public class TetherInterfaceStateMachine extends StateMachine {
    public TetherInterfaceStateMachine(
    public TetherInterfaceStateMachine(
            String ifaceName, Looper looper, int interfaceType, SharedLog log,
            String ifaceName, Looper looper, int interfaceType, SharedLog log,
            INetworkManagementService nMService, INetworkStatsService statsService,
            INetworkManagementService nMService, INetworkStatsService statsService,
            IControlsTethering tetherController) {
            IControlsTethering tetherController,
            TetheringDependencies deps) {
        super(ifaceName, looper);
        super(ifaceName, looper);
        mLog = log.forSubComponent(ifaceName);
        mLog = log.forSubComponent(ifaceName);
        mNMService = nMService;
        mNMService = nMService;
        // TODO: This should be passed in for testability.
        mNetd = deps.getNetdService();
        mNetd = NetdService.getInstance();
        mStatsService = statsService;
        mStatsService = statsService;
        mTetherController = tetherController;
        mTetherController = tetherController;
        mInterfaceCtrl = new InterfaceController(ifaceName, nMService, mNetd, mLog);
        mInterfaceCtrl = new InterfaceController(ifaceName, nMService, mNetd, mLog);
        mIfaceName = ifaceName;
        mIfaceName = ifaceName;
        mInterfaceType = interfaceType;
        mInterfaceType = interfaceType;
        mLinkProperties = new LinkProperties();
        mLinkProperties = new LinkProperties();
        mDeps = deps;
        resetLinkProperties();
        resetLinkProperties();
        mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
        mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
        mServingMode = IControlsTethering.STATE_AVAILABLE;
        mServingMode = IControlsTethering.STATE_AVAILABLE;
@@ -246,16 +249,14 @@ public class TetherInterfaceStateMachine extends StateMachine {
    }
    }


    private boolean startIPv6() {
    private boolean startIPv6() {
        // TODO: Refactor for better testability.  This is one of the things
        mInterfaceParams = mDeps.getInterfaceParams(mIfaceName);
        // that prohibits unittesting IPv6 tethering setup.
        mInterfaceParams = InterfaceParams.getByName(mIfaceName);
        if (mInterfaceParams == null) {
        if (mInterfaceParams == null) {
            mLog.e("Failed to find InterfaceParams");
            mLog.e("Failed to find InterfaceParams");
            stopIPv6();
            stopIPv6();
            return false;
            return false;
        }
        }


        mRaDaemon = new RouterAdvertisementDaemon(mInterfaceParams);
        mRaDaemon = mDeps.getRouterAdvertisementDaemon(mInterfaceParams);
        if (!mRaDaemon.start()) {
        if (!mRaDaemon.start()) {
            stopIPv6();
            stopIPv6();
            return false;
            return false;
+31 −0
Original line number Original line Diff line number Diff line
@@ -16,9 +16,18 @@


package com.android.server.connectivity.tethering;
package com.android.server.connectivity.tethering;


import android.content.Context;
import android.net.INetd;
import android.net.ip.RouterAdvertisementDaemon;
import android.net.util.InterfaceParams;
import android.net.util.NetdService;
import android.os.Handler;
import android.os.Handler;
import android.net.util.SharedLog;
import android.net.util.SharedLog;


import com.android.internal.util.StateMachine;

import java.util.ArrayList;



/**
/**
 * Capture tethering dependencies, for injection.
 * Capture tethering dependencies, for injection.
@@ -29,4 +38,26 @@ public class TetheringDependencies {
    public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
    public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
        return new OffloadHardwareInterface(h, log);
        return new OffloadHardwareInterface(h, log);
    }
    }

    public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx, StateMachine target,
            SharedLog log, int what) {
        return new UpstreamNetworkMonitor(ctx, target, log, what);
    }

    public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
            ArrayList<TetherInterfaceStateMachine> notifyList, SharedLog log) {
        return new IPv6TetheringCoordinator(notifyList, log);
    }

    public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
        return new RouterAdvertisementDaemon(ifParams);
    }

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

    public INetd getNetdService() {
        return NetdService.getInstance();
    }
}
}
+234 −71

File changed.

Preview size limit exceeded, changes collapsed.

+5 −5
Original line number Original line Diff line number Diff line
@@ -31,7 +31,6 @@ import static org.mockito.Mockito.when;
import static android.net.ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
import static android.net.ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
import static android.net.ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
import static android.net.ConnectivityManager.TETHERING_USB;
import static android.net.ConnectivityManager.TETHERING_USB;
import static android.net.ConnectivityManager.TETHERING_WIFI;
import static android.net.ConnectivityManager.TETHERING_WIFI;
@@ -39,7 +38,6 @@ import static com.android.server.connectivity.tethering.IControlsTethering.STATE
import static com.android.server.connectivity.tethering.IControlsTethering.STATE_TETHERED;
import static com.android.server.connectivity.tethering.IControlsTethering.STATE_TETHERED;
import static com.android.server.connectivity.tethering.IControlsTethering.STATE_UNAVAILABLE;
import static com.android.server.connectivity.tethering.IControlsTethering.STATE_UNAVAILABLE;


import android.net.ConnectivityManager;
import android.net.INetworkStatsService;
import android.net.INetworkStatsService;
import android.net.InterfaceConfiguration;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.LinkAddress;
@@ -75,6 +73,7 @@ public class TetherInterfaceStateMachineTest {
    @Mock private IControlsTethering mTetherHelper;
    @Mock private IControlsTethering mTetherHelper;
    @Mock private InterfaceConfiguration mInterfaceConfiguration;
    @Mock private InterfaceConfiguration mInterfaceConfiguration;
    @Mock private SharedLog mSharedLog;
    @Mock private SharedLog mSharedLog;
    @Mock private TetheringDependencies mTetheringDependencies;


    private final TestLooper mLooper = new TestLooper();
    private final TestLooper mLooper = new TestLooper();
    private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor =
    private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor =
@@ -84,7 +83,7 @@ public class TetherInterfaceStateMachineTest {
    private void initStateMachine(int interfaceType) throws Exception {
    private void initStateMachine(int interfaceType) throws Exception {
        mTestedSm = new TetherInterfaceStateMachine(
        mTestedSm = new TetherInterfaceStateMachine(
                IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog,
                IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog,
                mNMService, mStatsService, mTetherHelper);
                mNMService, mStatsService, mTetherHelper, mTetheringDependencies);
        mTestedSm.start();
        mTestedSm.start();
        // Starting the state machine always puts us in a consistent state and notifies
        // Starting the state machine always puts us in a consistent state and notifies
        // the rest of the world that we've changed from an unknown to available state.
        // the rest of the world that we've changed from an unknown to available state.
@@ -111,7 +110,8 @@ public class TetherInterfaceStateMachineTest {
    @Test
    @Test
    public void startsOutAvailable() {
    public void startsOutAvailable() {
        mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(),
        mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(),
                TETHERING_BLUETOOTH, mSharedLog, mNMService, mStatsService, mTetherHelper);
                TETHERING_BLUETOOTH, mSharedLog, mNMService, mStatsService, mTetherHelper,
                mTetheringDependencies);
        mTestedSm.start();
        mTestedSm.start();
        mLooper.dispatchAll();
        mLooper.dispatchAll();
        verify(mTetherHelper).updateInterfaceState(
        verify(mTetherHelper).updateInterfaceState(
@@ -346,7 +346,7 @@ public class TetherInterfaceStateMachineTest {
     * Send a command to the state machine under test, and run the event loop to idle.
     * Send a command to the state machine under test, and run the event loop to idle.
     *
     *
     * @param command One of the TetherInterfaceStateMachine.CMD_* constants.
     * @param command One of the TetherInterfaceStateMachine.CMD_* constants.
     * @param obj An additional argument to pass.
     * @param arg1 An additional argument to pass.
     */
     */
    private void dispatchCommand(int command, int arg1) {
    private void dispatchCommand(int command, int arg1) {
        mTestedSm.sendMessage(command, arg1);
        mTestedSm.sendMessage(command, arg1);
Loading