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

Commit e03fb445 authored by Christopher Wiley's avatar Christopher Wiley
Browse files

Make Tethering.TetherInterfaceSM more self contained

( cherry-pick of 9a509ca7 )

Remove references from the class into the containing class:
  - Move functionality to bring up a USB interface into the class itself.
  - Extract an interface to wrap methods where TetherInterfaceSM was
    calling into other private classes of Tethering
  - Inject necessary dependendencies into TetherInterfaceSM instances.

Bug: 28833951
Test: Compiles.

Change-Id: Ic96947417cf8734072d027b0f1cba8a1a1be7a74
parent b9cb7742
Loading
Loading
Loading
Loading
+81 −67
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.server.IoThread;
import com.android.server.connectivity.tethering.IControlsTethering;
import com.android.server.net.BaseNetworkObserver;

import java.io.FileDescriptor;
@@ -92,7 +93,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 *
 * TODO - look for parent classes and code sharing
 */
public class Tethering extends BaseNetworkObserver {
public class Tethering extends BaseNetworkObserver implements IControlsTethering {

    private final Context mContext;
    private final static String TAG = "Tethering";
@@ -264,7 +265,8 @@ public class Tethering extends BaseNetworkObserver {
            TetherInterfaceSM sm = mIfaces.get(iface);
            if (up) {
                if (sm == null) {
                    sm = new TetherInterfaceSM(iface, mLooper, usb, mPublicSync);
                    sm = new TetherInterfaceSM(iface, mLooper, usb, mPublicSync,
                            mNMService, mStatsService, this);
                    mIfaces.put(iface, sm);
                    sm.start();
                }
@@ -339,7 +341,8 @@ public class Tethering extends BaseNetworkObserver {
                if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
                return;
            }
            sm = new TetherInterfaceSM(iface, mLooper, usb, mPublicSync);
            sm = new TetherInterfaceSM(iface, mLooper, usb, mPublicSync,
                    mNMService, mStatsService, this);
            mIfaces.put(iface, sm);
            sm.start();
        }
@@ -632,7 +635,8 @@ public class Tethering extends BaseNetworkObserver {

    // TODO - move all private methods used only by the state machine into the state machine
    // to clarify what needs synchronized protection.
    private void sendTetherStateChangedBroadcast() {
    @Override
    public void sendTetherStateChangedBroadcast() {
        if (!getConnectivityManager().isTetheringSupported()) return;

        ArrayList<String> availableList = new ArrayList<String>();
@@ -809,44 +813,6 @@ public class Tethering extends BaseNetworkObserver {
        Log.e(TAG, "unable start or stop USB tethering");
    }

    // configured when we start tethering and unconfig'd on error or conclusion
    private boolean configureUsbIface(boolean enabled) {
        if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")");

        // toggle the USB interfaces
        String[] ifaces = new String[0];
        try {
            ifaces = mNMService.listInterfaces();
        } catch (Exception e) {
            Log.e(TAG, "Error listing Interfaces", e);
            return false;
        }
        for (String iface : ifaces) {
            if (isUsb(iface)) {
                InterfaceConfiguration ifcg = null;
                try {
                    ifcg = mNMService.getInterfaceConfig(iface);
                    if (ifcg != null) {
                        InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
                        ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH));
                        if (enabled) {
                            ifcg.setInterfaceUp();
                        } else {
                            ifcg.setInterfaceDown();
                        }
                        ifcg.clearFlag("running");
                        mNMService.setInterfaceConfig(iface, ifcg);
                    }
                } catch (Exception e) {
                    Log.e(TAG, "Error configuring interface " + iface, e);
                    return false;
                }
            }
         }

        return true;
    }

    // TODO - return copies so people can't tamper
    public String[] getTetherableUsbRegexs() {
        return mTetherableUsbRegexs;
@@ -1014,7 +980,12 @@ public class Tethering extends BaseNetworkObserver {
        }
    }

    class TetherInterfaceSM extends StateMachine {
    /**
     * @hide
     *
     * Tracks the eligibility of a given network interface for tethering.
     */
    public static class TetherInterfaceSM extends StateMachine {
        private static final int BASE_IFACE              = Protocol.BASE_TETHERING + 100;
        // notification from the master SM that it's not in tether mode
        static final int CMD_TETHER_MODE_DEAD            = BASE_IFACE + 1;
@@ -1046,6 +1017,10 @@ public class Tethering extends BaseNetworkObserver {
        private final State mTetheredState;
        private final State mUnavailableState;

        private final INetworkManagementService mNMService;
        private final INetworkStatsService mStatsService;
        private final IControlsTethering mTetherController;

        private final boolean mUsb;
        private final String mIfaceName;

@@ -1055,12 +1030,17 @@ public class Tethering extends BaseNetworkObserver {
        private int mLastError;
        private String mMyUpstreamIfaceName;  // may change over time

        TetherInterfaceSM(String name, Looper looper, boolean usb, Object mutex) {
            super(name, looper);
            mIfaceName = name;
        TetherInterfaceSM(String ifaceName, Looper looper, boolean usb, Object mutex,
                        INetworkManagementService nMService, INetworkStatsService statsService,
                        IControlsTethering tetherController) {
            super(ifaceName, looper);
            mNMService = nMService;
            mStatsService = statsService;
            mTetherController = tetherController;
            mIfaceName = ifaceName;
            mUsb = usb;
            setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
            mMutex = mutex;
            setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);

            mInitialState = new InitialState();
            addState(mInitialState);
@@ -1103,7 +1083,7 @@ public class Tethering extends BaseNetworkObserver {
                    if (mUsb) {
                        // note everything's been unwound by this point so nothing to do on
                        // further error..
                        Tethering.this.configureUsbIface(false);
                        configureUsbIface(false, mIfaceName);
                    }
                }
            }
@@ -1139,12 +1119,45 @@ public class Tethering extends BaseNetworkObserver {
            }
        }

        // configured when we start tethering and unconfig'd on error or conclusion
        private boolean configureUsbIface(boolean enabled, String iface) {
            if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")");

            InterfaceConfiguration ifcg = null;
            try {
                ifcg = mNMService.getInterfaceConfig(iface);
                if (ifcg != null) {
                    InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
                    ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH));
                    if (enabled) {
                        ifcg.setInterfaceUp();
                    } else {
                        ifcg.setInterfaceDown();
                    }
                    ifcg.clearFlag("running");
                    mNMService.setInterfaceConfig(iface, ifcg);
                }
            } catch (Exception e) {
                Log.e(TAG, "Error configuring interface " + iface, e);
                return false;
            }

            return true;
        }

        private void maybeLogMessage(State state, int what) {
            if (DBG) {
                Log.d(TAG, state.getName() + " got " +
                        sMagicDecoderRing.get(what, Integer.toString(what)));
            }
        }

        class InitialState extends State {
            @Override
            public void enter() {
                setAvailable(true);
                setTethered(false);
                sendTetherStateChangedBroadcast();
                mTetherController.sendTetherStateChangedBroadcast();
            }

            @Override
@@ -1154,8 +1167,7 @@ public class Tethering extends BaseNetworkObserver {
                switch (message.what) {
                    case CMD_TETHER_REQUESTED:
                        setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
                        mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED,
                                TetherInterfaceSM.this);
                        mTetherController.notifyInterfaceTetheringReadiness(true, TetherInterfaceSM.this);
                        transitionTo(mStartingState);
                        break;
                    case CMD_INTERFACE_DOWN:
@@ -1174,16 +1186,15 @@ public class Tethering extends BaseNetworkObserver {
            public void enter() {
                setAvailable(false);
                if (mUsb) {
                    if (!Tethering.this.configureUsbIface(true)) {
                        mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
                                TetherInterfaceSM.this);
                    if (!configureUsbIface(true, mIfaceName)) {
                        mTetherController.notifyInterfaceTetheringReadiness(false, TetherInterfaceSM.this);
                        setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);

                        transitionTo(mInitialState);
                        return;
                    }
                }
                sendTetherStateChangedBroadcast();
                mTetherController.sendTetherStateChangedBroadcast();

                // Skipping StartingState
                transitionTo(mTetheredState);
@@ -1195,10 +1206,9 @@ public class Tethering extends BaseNetworkObserver {
                switch (message.what) {
                    // maybe a parent class?
                    case CMD_TETHER_UNREQUESTED:
                        mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
                                TetherInterfaceSM.this);
                        mTetherController.notifyInterfaceTetheringReadiness(false, TetherInterfaceSM.this);
                        if (mUsb) {
                            if (!Tethering.this.configureUsbIface(false)) {
                            if (!configureUsbIface(false, mIfaceName)) {
                                setLastErrorAndTransitionToInitialState(
                                    ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
                                break;
@@ -1216,8 +1226,7 @@ public class Tethering extends BaseNetworkObserver {
                                ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
                        break;
                    case CMD_INTERFACE_DOWN:
                        mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
                                TetherInterfaceSM.this);
                        mTetherController.notifyInterfaceTetheringReadiness(false, TetherInterfaceSM.this);
                        transitionTo(mUnavailableState);
                        break;
                    default:
@@ -1247,7 +1256,7 @@ public class Tethering extends BaseNetworkObserver {
                if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
                setAvailable(false);
                setTethered(true);
                sendTetherStateChangedBroadcast();
                mTetherController.sendTetherStateChangedBroadcast();
            }

            private void cleanupUpstream() {
@@ -1294,11 +1303,10 @@ public class Tethering extends BaseNetworkObserver {
                                    ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
                            break;
                        }
                        mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
                                TetherInterfaceSM.this);
                        mTetherController.notifyInterfaceTetheringReadiness(false, TetherInterfaceSM.this);
                        if (message.what == CMD_TETHER_UNREQUESTED) {
                            if (mUsb) {
                                if (!Tethering.this.configureUsbIface(false)) {
                                if (!configureUsbIface(false, mIfaceName)) {
                                    setLastError(
                                            ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
                                }
@@ -1362,9 +1370,9 @@ public class Tethering extends BaseNetworkObserver {
                            break;
                        }
                        if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
                        sendTetherStateChangedBroadcast();
                        mTetherController.sendTetherStateChangedBroadcast();
                        if (mUsb) {
                            if (!Tethering.this.configureUsbIface(false)) {
                            if (!configureUsbIface(false, mIfaceName)) {
                                setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
                            }
                        }
@@ -1384,7 +1392,7 @@ public class Tethering extends BaseNetworkObserver {
                setAvailable(false);
                setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
                setTethered(false);
                sendTetherStateChangedBroadcast();
                mTetherController.sendTetherStateChangedBroadcast();
            }
            @Override
            public boolean processMessage(Message message) {
@@ -2104,4 +2112,10 @@ public class Tethering extends BaseNetworkObserver {
        }
        pw.decreaseIndent();
    }

    @Override
    public void notifyInterfaceTetheringReadiness(boolean isReady, TetherInterfaceSM who) {
        mTetherMasterSM.sendMessage((isReady) ? TetherMasterSM.CMD_TETHER_MODE_REQUESTED
                                              : TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, who);
    }
}
+29 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.connectivity.tethering;

import com.android.server.connectivity.Tethering;

/**
 * @hide
 *
 * Interface with methods necessary to notify that a given interface is ready for tethering.
 */
public interface IControlsTethering {
    void sendTetherStateChangedBroadcast();
    void notifyInterfaceTetheringReadiness(boolean isReady, Tethering.TetherInterfaceSM who);
}
 No newline at end of file