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

Commit cacf1981 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Convert IControlsTethering from interface into callback" into oc-dr1-dev

parents 1761985e 6e9a1010
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;
                }
@@ -1397,6 +1403,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
            if (mode == IControlsTethering.STATE_TETHERED) {
                mForwardedDownstreams.add(who);
            } else {
                mOffloadController.removeDownstreamInterface(who.interfaceName());
                mForwardedDownstreams.remove(who);
            }

@@ -1421,6 +1428,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.
@@ -1524,6 +1532,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;
@@ -1748,9 +1765,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)) {
@@ -1796,6 +1829,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);
@@ -1813,7 +1864,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();
@@ -1825,7 +1877,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