Merge "Refactor and improve logging." am: c3d41d5093 am: 8af8235bca

am: 9f76683c59

Change-Id: Ieb9a8e3f85f41d18056a7827997f12986ff13ca1
This commit is contained in:
Erik Kline
2017-05-09 10:53:36 +00:00
committed by android-build-merger
2 changed files with 125 additions and 54 deletions

View File

@@ -62,6 +62,7 @@ import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.LocalLog;
import android.util.Log;
import android.util.SparseArray;
@@ -147,6 +148,10 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
}
}
private final static int MAX_LOG_RECORDS = 500;
private final LocalLog mLocalLog = new LocalLog(MAX_LOG_RECORDS);
// used to synchronize public access to members
private final Object mPublicSync;
private final Context mContext;
@@ -177,6 +182,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
public Tethering(Context context, INetworkManagementService nmService,
INetworkStatsService statsService, INetworkPolicyManager policyManager,
Looper looper, MockableSystemProperties systemProperties) {
mLocalLog.log("CONSTRUCTED");
mContext = context;
mNMService = nmService;
mStatsService = statsService;
@@ -980,7 +986,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
return ConnectivityManager.TETHER_ERROR_NO_ERROR;
}
// TODO review API - maybe return ArrayList<String> here and below?
// TODO review API - figure out how to delete these entirely.
public String[] getTetheredIfaces() {
ArrayList<String> list = new ArrayList<String>();
synchronized (mPublicSync) {
@@ -1123,19 +1129,19 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
//Add states
mInitialState = new InitialState();
addState(mInitialState);
mTetherModeAliveState = new TetherModeAliveState();
addState(mTetherModeAliveState);
mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
addState(mSetIpForwardingEnabledErrorState);
mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
addState(mSetIpForwardingDisabledErrorState);
mStartTetheringErrorState = new StartTetheringErrorState();
addState(mStartTetheringErrorState);
mStopTetheringErrorState = new StopTetheringErrorState();
addState(mStopTetheringErrorState);
mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
addState(mInitialState);
addState(mTetherModeAliveState);
addState(mSetIpForwardingEnabledErrorState);
addState(mSetIpForwardingDisabledErrorState);
addState(mStartTetheringErrorState);
addState(mStopTetheringErrorState);
addState(mSetDnsForwardersErrorState);
mNotifyList = new ArrayList<>();
@@ -1143,6 +1149,29 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
setInitialState(mInitialState);
}
class InitialState extends State {
@Override
public boolean processMessage(Message message) {
maybeLogMessage(this, message.what);
switch (message.what) {
case EVENT_IFACE_SERVING_STATE_ACTIVE:
TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
handleInterfaceServingStateActive(message.arg1, who);
transitionTo(mTetherModeAliveState);
break;
case EVENT_IFACE_SERVING_STATE_INACTIVE:
who = (TetherInterfaceStateMachine)message.obj;
if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
handleInterfaceServingStateInactive(who);
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
}
class TetherMasterUtilState extends State {
@Override
public boolean processMessage(Message m) {
@@ -1163,6 +1192,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
try {
mNMService.setIpForwardingEnabled(true);
} catch (Exception e) {
mLocalLog.log("ERROR " + e);
transitionTo(mSetIpForwardingEnabledErrorState);
return false;
}
@@ -1175,10 +1205,12 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
mNMService.stopTethering();
mNMService.startTethering(cfg.dhcpRanges);
} catch (Exception ee) {
mLocalLog.log("ERROR " + ee);
transitionTo(mStartTetheringErrorState);
return false;
}
}
mLocalLog.log("SET master tether settings: ON");
return true;
}
@@ -1186,16 +1218,19 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
try {
mNMService.stopTethering();
} catch (Exception e) {
mLocalLog.log("ERROR " + e);
transitionTo(mStopTetheringErrorState);
return false;
}
try {
mNMService.setIpForwardingEnabled(false);
} catch (Exception e) {
mLocalLog.log("ERROR " + e);
transitionTo(mSetIpForwardingDisabledErrorState);
return false;
}
transitionTo(mInitialState);
mLocalLog.log("SET master tether settings: OFF");
return true;
}
@@ -1319,16 +1354,15 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
// TODO: remove this invocation of NetworkUtils.makeStrings().
dnsServers = NetworkUtils.makeStrings(dnses);
}
if (VDBG) {
Log.d(TAG, "Setting DNS forwarders: Network=" + network +
", dnsServers=" + Arrays.toString(dnsServers));
}
try {
mNMService.setDnsForwarders(network, dnsServers);
mLocalLog.log(String.format(
"SET DNS forwarders: network=%s dnsServers=[%s]",
network, Arrays.toString(dnsServers)));
} catch (Exception e) {
// TODO: Investigate how this can fail and what exactly
// happens if/when such failures occur.
Log.e(TAG, "Setting DNS forwarders failed!");
mLocalLog.log("ERROR setting DNS forwarders failed, " + e);
transitionTo(mSetDnsForwardersErrorState);
}
}
@@ -1393,39 +1427,18 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
}
}
class InitialState extends State {
@Override
public boolean processMessage(Message message) {
maybeLogMessage(this, message.what);
boolean retValue = true;
switch (message.what) {
case EVENT_IFACE_SERVING_STATE_ACTIVE:
TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
handleInterfaceServingStateActive(message.arg1, who);
transitionTo(mTetherModeAliveState);
break;
case EVENT_IFACE_SERVING_STATE_INACTIVE:
who = (TetherInterfaceStateMachine)message.obj;
if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
handleInterfaceServingStateInactive(who);
break;
default:
retValue = false;
break;
}
return retValue;
}
}
class TetherModeAliveState extends TetherMasterUtilState {
boolean mUpstreamWanted = false;
boolean mTryCell = true;
@Override
public void enter() {
// TODO: examine if we should check the return value.
turnOnMasterTetherSettings(); // may transition us out
// If turning on master tether settings fails, we have already
// transitioned to an error state; exit early.
if (!turnOnMasterTetherSettings()) {
return;
}
mSimChange.startListening();
mUpstreamNetworkMonitor.start();
mOffloadController.start();
@@ -1478,14 +1491,16 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
handleInterfaceServingStateInactive(who);
if (mNotifyList.isEmpty()) {
turnOffMasterTetherSettings(); // transitions appropriately
} else {
if (DBG) {
Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
" live requests:");
for (TetherInterfaceStateMachine o : mNotifyList) {
Log.d(TAG, " " + o);
}
// transitions appropriately
turnOffMasterTetherSettings();
break;
}
if (DBG) {
Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
" live requests:");
for (TetherInterfaceStateMachine o : mNotifyList) {
Log.d(TAG, " " + o);
}
}
// If there has been a change and an upstream is no
@@ -1699,6 +1714,12 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
pw.println("Upstream wanted: " + upstreamWanted());
pw.decreaseIndent();
}
pw.println("Log:");
pw.increaseIndent();
mLocalLog.readOnlyLocalLog().dump(fd, pw, args);
pw.decreaseIndent();
pw.decreaseIndent();
}
@@ -1715,10 +1736,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
}
}
if (DBG) {
Log.d(TAG, "iface " + iface + " notified that it was in state " + state +
" with error " + error);
}
mLocalLog.log(String.format("OBSERVED iface=%s state=%s error=%s",
iface, state, error));
try {
// Notify that we're tethering (or not) this interface.

View File

@@ -18,12 +18,13 @@ package com.android.server.connectivity;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -47,6 +48,7 @@ import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.test.TestLooper;
import android.os.UserHandle;
import android.support.test.filters.SmallTest;
@@ -352,6 +354,56 @@ public class TetheringTest {
mTethering.getLastTetherError(mTestIfname));
}
// TODO: Test that a request for hotspot mode doesn't interface with an
@Test
public void failureEnablingIpForwarding() throws Exception {
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
// Emulate pressing the WiFi tethering button.
mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startSoftAp(null);
verifyNoMoreInteractions(mWifiManager);
verifyNoMoreInteractions(mConnectivityManager);
verifyNoMoreInteractions(mNMService);
// Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that
// tethering mode is to be started.
mTethering.interfaceStatusChanged(mTestIfname, true);
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
mLooper.dispatchAll();
// Activity caused by test_wlan0 becoming available.
verify(mNMService, times(1)).listInterfaces();
// We verify get/set called twice here: once for setup and once during
// teardown because all events happen over the course of the single
// dispatchAll() above.
verify(mNMService, times(2)).getInterfaceConfig(mTestIfname);
verify(mNMService, times(2))
.setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
verify(mNMService, times(1)).tetherInterface(mTestIfname);
verify(mWifiManager).updateInterfaceIpState(
mTestIfname, WifiManager.IFACE_IP_MODE_TETHERED);
verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
// This is called, but will throw.
verify(mNMService, times(1)).setIpForwardingEnabled(true);
// This never gets called because of the exception thrown above.
verify(mNMService, times(0)).startTethering(any(String[].class));
// When the master state machine transitions to an error state it tells
// downstream interfaces, which causes us to tell Wi-Fi about the error
// so it can take down AP mode.
verify(mNMService, times(1)).untetherInterface(mTestIfname);
verify(mWifiManager).updateInterfaceIpState(
mTestIfname, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
verifyNoMoreInteractions(mWifiManager);
verifyNoMoreInteractions(mConnectivityManager);
verifyNoMoreInteractions(mNMService);
}
// TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface.
}