From 9a509ca728fbe264e1a5a6ccd5b39ffc0b5eceb4 Mon Sep 17 00:00:00 2001 From: Christopher Wiley Date: Wed, 18 May 2016 13:45:20 -0700 Subject: [PATCH] Make Tethering.TetherInterfaceSM more self contained 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 --- .../server/connectivity/Tethering.java | 148 ++++++++++-------- .../tethering/IControlsTethering.java | 29 ++++ 2 files changed, 110 insertions(+), 67 deletions(-) create mode 100644 services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index 87dcfd3b5f7be..ac51a9e267bac 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -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 availableList = new ArrayList(); @@ -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); + } } diff --git a/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java b/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java new file mode 100644 index 0000000000000..5eed26cc15979 --- /dev/null +++ b/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java @@ -0,0 +1,29 @@ +/* + * 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