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

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

Merge "Convert IControlsTethering from interface into callback" am: 5b9d362b

am: ad3fd82f

Change-Id: Ib1f41df1200378191c0722a280939ccbde539920
parents d614cd35 ad3fd82f
Loading
Loading
Loading
Loading
+59 −7
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 * This class holds much of the business logic to allow Android devices
 * to act as IP gateways via USB, BT, and WiFi interfaces.
 */
public class Tethering extends BaseNetworkObserver implements IControlsTethering {
public class Tethering extends BaseNetworkObserver {

    private final static String TAG = Tethering.class.getSimpleName();
    private final static boolean DBG = false;
@@ -173,6 +173,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
    private final StateMachine mTetherMasterSM;
    private final OffloadController mOffloadController;
    private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
    // TODO: Figure out how to merge this and other downstream-tracking objects
    // into a single coherent structure.
    private final HashSet<TetherInterfaceStateMachine> mForwardedDownstreams;
    private final SimChangeListener mSimChange;

@@ -184,7 +186,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
    private boolean mRndisEnabled;       // track the RNDIS function enabled state
    private boolean mUsbTetherRequested; // true if USB tethering should be started
                                         // when RNDIS is enabled
    // True iff WiFi tethering should be started when soft AP is ready.
    // True iff. WiFi tethering should be started when soft AP is ready.
    private boolean mWifiTetherRequested;

    public Tethering(Context context, INetworkManagementService nmService,
@@ -1112,6 +1114,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
        static final int EVENT_UPSTREAM_CALLBACK                = BASE_MASTER + 5;
        // we treated the error and want now to clear it
        static final int CMD_CLEAR_ERROR                        = BASE_MASTER + 6;
        static final int EVENT_IFACE_UPDATE_LINKPROPERTIES      = BASE_MASTER + 7;

        private State mInitialState;
        private State mTetherModeAliveState;
@@ -1179,6 +1182,9 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                        if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
                        handleInterfaceServingStateInactive(who);
                        break;
                    case EVENT_IFACE_UPDATE_LINKPROPERTIES:
                        // Silently ignore these for now.
                        break;
                    default:
                        return NOT_HANDLED;
                }
@@ -1345,6 +1351,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
            if (mode == IControlsTethering.STATE_TETHERED) {
                mForwardedDownstreams.add(who);
            } else {
                mOffloadController.removeDownstreamInterface(who.interfaceName());
                mForwardedDownstreams.remove(who);
            }

@@ -1369,6 +1376,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
        private void handleInterfaceServingStateInactive(TetherInterfaceStateMachine who) {
            mNotifyList.remove(who);
            mIPv6TetheringCoordinator.removeActiveDownstream(who);
            mOffloadController.removeDownstreamInterface(who.interfaceName());
            mForwardedDownstreams.remove(who);

            // If this is a Wi-Fi interface, tell WifiManager of any errors.
@@ -1472,6 +1480,15 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                        }
                        break;
                    }
                    case EVENT_IFACE_UPDATE_LINKPROPERTIES: {
                        final LinkProperties newLp = (LinkProperties) message.obj;
                        if (message.arg1 == IControlsTethering.STATE_TETHERED) {
                            mOffloadController.notifyDownstreamLinkProperties(newLp);
                        } else {
                            mOffloadController.removeDownstreamInterface(newLp.getInterfaceName());
                        }
                        break;
                    }
                    case CMD_UPSTREAM_CHANGED:
                        updateUpstreamWanted();
                        if (!mUpstreamWanted) break;
@@ -1696,9 +1713,25 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
        return false;
    }

    private IControlsTethering makeControlCallback(String ifname) {
        return new IControlsTethering() {
            @Override
    public void notifyInterfaceStateChange(String iface, TetherInterfaceStateMachine who,
                                           int state, int error) {
            public void updateInterfaceState(
                    TetherInterfaceStateMachine who, int state, int lastError) {
                notifyInterfaceStateChange(ifname, who, state, lastError);
            }

            @Override
            public void updateLinkProperties(
                    TetherInterfaceStateMachine who, LinkProperties newLp) {
                notifyLinkPropertiesChanged(ifname, who, newLp);
            }
        };
    }

    // TODO: Move into TetherMasterSM.
    private void notifyInterfaceStateChange(
            String iface, TetherInterfaceStateMachine who, int state, int error) {
        synchronized (mPublicSync) {
            final TetherState tetherState = mTetherStates.get(iface);
            if (tetherState != null && tetherState.stateMachine.equals(who)) {
@@ -1744,6 +1777,24 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
        sendTetherStateChangedBroadcast();
    }

    private void notifyLinkPropertiesChanged(String iface, TetherInterfaceStateMachine who,
                                             LinkProperties newLp) {
        final int state;
        synchronized (mPublicSync) {
            final TetherState tetherState = mTetherStates.get(iface);
            if (tetherState != null && tetherState.stateMachine.equals(who)) {
                state = tetherState.lastState;
            } else {
                mLog.log("got notification from stale iface " + iface);
                return;
            }
        }

        mLog.log(String.format("OBSERVED LinkProperties update iface=%s state=%s", iface, state));
        final int which = TetherMasterSM.EVENT_IFACE_UPDATE_LINKPROPERTIES;
        mTetherMasterSM.sendMessage(which, state, 0, newLp);
    }

    private void maybeTrackNewInterfaceLocked(final String iface) {
        // If we don't care about this type of interface, ignore.
        final int interfaceType = ifaceNameToType(iface);
@@ -1761,7 +1812,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
        mLog.log("adding TetheringInterfaceStateMachine for: " + iface);
        final TetherState tetherState = new TetherState(
                new TetherInterfaceStateMachine(
                    iface, mLooper, interfaceType, mLog, mNMService, mStatsService, this,
                    iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
                    makeControlCallback(iface),
                    new IPv6TetheringInterfaceServices(iface, mNMService, mLog)));
        mTetherStates.put(iface, tetherState);
        tetherState.stateMachine.start();
@@ -1773,7 +1825,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
            mLog.log("attempting to remove unknown iface (" + iface + "), ignoring");
            return;
        }
        tetherState.stateMachine.sendMessage(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
        tetherState.stateMachine.stop();
        mLog.log("removing TetheringInterfaceStateMachine for: " + iface);
        mTetherStates.remove(iface);
    }
+25 −9
Original line number Diff line number Diff line
@@ -16,25 +16,41 @@

package com.android.server.connectivity.tethering;

import android.net.LinkProperties;

/**
 * @hide
 *
 * Interface with methods necessary to notify that a given interface is ready for tethering.
 *
 * Rename to something more representative, e.g. IpServingControlCallback.
 *
 * All methods MUST be called on the TetherMasterSM main Looper's thread.
 */
public interface IControlsTethering {
    public final int STATE_UNAVAILABLE = 0;
    public final int STATE_AVAILABLE   = 1;
    public final int STATE_TETHERED    = 2;
    public final int STATE_LOCAL_ONLY  = 3;
public class IControlsTethering {
    public static final int STATE_UNAVAILABLE = 0;
    public static final int STATE_AVAILABLE   = 1;
    public static final int STATE_TETHERED    = 2;
    public static final int STATE_LOCAL_ONLY  = 3;

    /**
     * Notify that |who| has changed its tethering state.  This may be called from any thread.
     * Notify that |who| has changed its tethering state.
     *
     * TODO: Remove the need for the |who| argument.
     *
     * @param iface a network interface (e.g. "wlan0")
     * @param who corresponding instance of a TetherInterfaceStateMachine
     * @param state one of IControlsTethering.STATE_*
     * @param lastError one of ConnectivityManager.TETHER_ERROR_*
     */
    void notifyInterfaceStateChange(String iface, TetherInterfaceStateMachine who,
                                    int state, int lastError);
    public void updateInterfaceState(TetherInterfaceStateMachine who, int state, int lastError) {}

    /**
     * Notify that |who| has new LinkProperties.
     *
     * TODO: Remove the need for the |who| argument.
     *
     * @param who corresponding instance of a TetherInterfaceStateMachine
     * @param newLp the new LinkProperties to report
     */
    public void updateLinkProperties(TetherInterfaceStateMachine who, LinkProperties newLp) {}
}
+13 −1
Original line number Diff line number Diff line
@@ -105,7 +105,19 @@ public class OffloadController {
        pushUpstreamParameters();
    }

    // TODO: public void addDownStream(...)
    public void notifyDownstreamLinkProperties(LinkProperties lp) {
        if (!started()) return;

        // TODO: Cache LinkProperties on a per-ifname basis and compute the
        // deltas, calling addDownstream()/removeDownstream() accordingly.
    }

    public void removeDownstreamInterface(String ifname) {
        if (!started()) return;

        // TODO: Check cache for LinkProperties of ifname and, if present,
        // call removeDownstream() accordingly.
    }

    private boolean isOffloadDisabled() {
        // Defaults to |false| if not present.
+13 −6
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ public class TetherInterfaceStateMachine extends StateMachine {

    private final String mIfaceName;
    private final int mInterfaceType;
    private final LinkProperties mLinkProperties;
    private final IPv6TetheringInterfaceServices mIPv6TetherSvc;

    private int mLastError;
@@ -106,6 +107,8 @@ public class TetherInterfaceStateMachine extends StateMachine {
        mTetherController = tetherController;
        mIfaceName = ifaceName;
        mInterfaceType = interfaceType;
        mLinkProperties = new LinkProperties();
        mLinkProperties.setInterfaceName(mIfaceName);
        mIPv6TetherSvc = ipv6Svc;
        mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;

@@ -127,6 +130,8 @@ public class TetherInterfaceStateMachine extends StateMachine {

    public int lastError() { return mLastError; }

    public void stop() { sendMessage(CMD_INTERFACE_DOWN); }

    // configured when we start tethering and unconfig'd on error or conclusion
    private boolean configureIfaceIp(boolean enabled) {
        if (VDBG) Log.d(TAG, "configureIfaceIp(" + enabled + ")");
@@ -182,8 +187,12 @@ public class TetherInterfaceStateMachine extends StateMachine {
    }

    private void sendInterfaceState(int newInterfaceState) {
        mTetherController.notifyInterfaceStateChange(
                mIfaceName, TetherInterfaceStateMachine.this, newInterfaceState, mLastError);
        mTetherController.updateInterfaceState(
                TetherInterfaceStateMachine.this, newInterfaceState, mLastError);
        // TODO: Populate mLinkProperties correctly, and send more sensible
        // updates more frequently (not just here).
        mTetherController.updateLinkProperties(
                TetherInterfaceStateMachine.this, new LinkProperties(mLinkProperties));
    }

    class InitialState extends State {
@@ -195,7 +204,6 @@ public class TetherInterfaceStateMachine extends StateMachine {
        @Override
        public boolean processMessage(Message message) {
            maybeLogMessage(this, message.what);
            boolean retValue = true;
            switch (message.what) {
                case CMD_TETHER_REQUESTED:
                    mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
@@ -218,10 +226,9 @@ public class TetherInterfaceStateMachine extends StateMachine {
                            (LinkProperties) message.obj);
                    break;
                default:
                    retValue = false;
                    break;
                    return NOT_HANDLED;
            }
            return retValue;
            return HANDLED;
        }
    }

+39 −19
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package com.android.server.connectivity.tethering;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.reset;
@@ -38,6 +40,7 @@ import static com.android.server.connectivity.tethering.IControlsTethering.STATE
import android.net.ConnectivityManager;
import android.net.INetworkStatsService;
import android.net.InterfaceConfiguration;
import android.net.LinkProperties;
import android.net.util.SharedLog;
import android.os.INetworkManagementService;
import android.os.RemoteException;
@@ -103,8 +106,9 @@ public class TetherInterfaceStateMachineTest {
                mIPv6TetheringInterfaceServices);
        mTestedSm.start();
        mLooper.dispatchAll();
        verify(mTetherHelper).notifyInterfaceStateChange(
                IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
        verify(mTetherHelper).updateInterfaceState(
                mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
        verify(mTetherHelper).updateLinkProperties(eq(mTestedSm), any(LinkProperties.class));
        verifyNoMoreInteractions(mTetherHelper, mNMService, mStatsService);
    }

@@ -133,8 +137,9 @@ public class TetherInterfaceStateMachineTest {
        initStateMachine(TETHERING_BLUETOOTH);

        dispatchCommand(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
        verify(mTetherHelper).notifyInterfaceStateChange(
                IFACE_NAME, mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
        verify(mTetherHelper).updateInterfaceState(
                mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
        verify(mTetherHelper).updateLinkProperties(eq(mTestedSm), any(LinkProperties.class));
        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
    }

@@ -145,8 +150,10 @@ public class TetherInterfaceStateMachineTest {
        dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
        InOrder inOrder = inOrder(mTetherHelper, mNMService);
        inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
        inOrder.verify(mTetherHelper).notifyInterfaceStateChange(
                IFACE_NAME, mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
        inOrder.verify(mTetherHelper).updateInterfaceState(
                mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
        inOrder.verify(mTetherHelper).updateLinkProperties(
                eq(mTestedSm), any(LinkProperties.class));
        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
    }

@@ -157,8 +164,10 @@ public class TetherInterfaceStateMachineTest {
        dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
        InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
        inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
        inOrder.verify(mTetherHelper).notifyInterfaceStateChange(
                IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
        inOrder.verify(mTetherHelper).updateInterfaceState(
                mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
        inOrder.verify(mTetherHelper).updateLinkProperties(
                eq(mTestedSm), any(LinkProperties.class));
        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
    }

@@ -171,8 +180,10 @@ public class TetherInterfaceStateMachineTest {
        inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
        inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
        inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
        inOrder.verify(mTetherHelper).notifyInterfaceStateChange(
                IFACE_NAME, mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
        inOrder.verify(mTetherHelper).updateInterfaceState(
                mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
        inOrder.verify(mTetherHelper).updateLinkProperties(
                eq(mTestedSm), any(LinkProperties.class));
        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
    }

@@ -180,7 +191,8 @@ public class TetherInterfaceStateMachineTest {
    public void handlesFirstUpstreamChange() throws Exception {
        initTetheredStateMachine(TETHERING_BLUETOOTH, null);

        // Telling the state machine about its upstream interface triggers a little more configuration.
        // Telling the state machine about its upstream interface triggers
        // a little more configuration.
        dispatchTetherConnectionChanged(UPSTREAM_IFACE);
        InOrder inOrder = inOrder(mNMService);
        inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE);
@@ -248,8 +260,10 @@ public class TetherInterfaceStateMachineTest {
        inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
        inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
        inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
        inOrder.verify(mTetherHelper).notifyInterfaceStateChange(
                IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
        inOrder.verify(mTetherHelper).updateInterfaceState(
                mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
        inOrder.verify(mTetherHelper).updateLinkProperties(
                eq(mTestedSm), any(LinkProperties.class));
        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
    }

@@ -266,8 +280,10 @@ public class TetherInterfaceStateMachineTest {
            usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
            usbTeardownOrder.verify(mNMService).setInterfaceConfig(
                    IFACE_NAME, mInterfaceConfiguration);
            usbTeardownOrder.verify(mTetherHelper).notifyInterfaceStateChange(
                    IFACE_NAME, mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
            usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
                    mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
            usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
                    eq(mTestedSm), any(LinkProperties.class));
        }
    }

@@ -281,8 +297,10 @@ public class TetherInterfaceStateMachineTest {
        usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
        usbTeardownOrder.verify(mNMService).setInterfaceConfig(
                IFACE_NAME, mInterfaceConfiguration);
        usbTeardownOrder.verify(mTetherHelper).notifyInterfaceStateChange(
                IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
        usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
                mTestedSm, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
        usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
                eq(mTestedSm), any(LinkProperties.class));
    }

    @Test
@@ -294,8 +312,10 @@ public class TetherInterfaceStateMachineTest {
        InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
        usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
        usbTeardownOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
        usbTeardownOrder.verify(mTetherHelper).notifyInterfaceStateChange(
                IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
        usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
                mTestedSm, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
        usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
                eq(mTestedSm), any(LinkProperties.class));
    }

    @Test