diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 50c0a124fb..1edc5366bb 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -89,7 +89,6 @@ import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemClock; -import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -203,6 +202,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS private final int mReleasePendingIntentDelayMs; + private MockableSystemProperties mSystemProperties; + private Tethering mTethering; private final PermissionMonitor mPermissionMonitor; @@ -675,6 +676,8 @@ public class ConnectivityService extends IConnectivityManager.Stub IpConnectivityLog logger) { if (DBG) log("ConnectivityService starting up"); + mSystemProperties = getSystemProperties(); + mMetricsLog = logger; mDefaultRequest = createInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST); NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder()); @@ -692,7 +695,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000); - mLingerDelayMs = SystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); + mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); mContext = checkNotNull(context, "missing Context"); mNetd = checkNotNull(netManager, "missing INetworkManagementService"); @@ -722,7 +725,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1]; // TODO: What is the "correct" way to do determine if this is a wifi only device? - boolean wifiOnly = SystemProperties.getBoolean("ro.radio.noril", false); + boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false); log("wifiOnly=" + wifiOnly); String[] naStrings = context.getResources().getStringArray( com.android.internal.R.array.networkAttributes); @@ -775,8 +778,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - mTestMode = SystemProperties.get("cm.test.mode").equals("true") - && SystemProperties.get("ro.build.type").equals("eng"); + mTestMode = mSystemProperties.get("cm.test.mode").equals("true") + && mSystemProperties.get("ro.build.type").equals("eng"); mTethering = new Tethering(mContext, mNetd, statsService, mPolicyManager, IoThread.get().getLooper(), new MockableSystemProperties()); @@ -1732,8 +1735,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // Overridden for testing purposes to avoid writing to SystemProperties. @VisibleForTesting - protected int getDefaultTcpRwnd() { - return SystemProperties.getInt(DEFAULT_TCP_RWND_KEY, 0); + protected MockableSystemProperties getSystemProperties() { + return new MockableSystemProperties(); } private void updateTcpBufferSizes(NetworkAgentInfo nai) { @@ -1771,10 +1774,11 @@ public class ConnectivityService extends IConnectivityManager.Stub } Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.TCP_DEFAULT_INIT_RWND, getDefaultTcpRwnd()); + Settings.Global.TCP_DEFAULT_INIT_RWND, + mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)); final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd"; if (rwndValue != 0) { - SystemProperties.set(sysctlKey, rwndValue.toString()); + mSystemProperties.set(sysctlKey, rwndValue.toString()); } } @@ -1798,7 +1802,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public int getRestoreDefaultNetworkDelay(int networkType) { - String restoreDefaultNetworkDelayStr = SystemProperties.get( + String restoreDefaultNetworkDelayStr = mSystemProperties.get( NETWORK_RESTORE_DELAY_PROP_NAME); if(restoreDefaultNetworkDelayStr != null && restoreDefaultNetworkDelayStr.length() != 0) { @@ -2965,7 +2969,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public boolean isTetheringSupported() { enforceTetherAccessPermission(); - int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); + int defaultVal = (mSystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.TETHER_SUPPORTED, defaultVal) != 0) && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING); @@ -4468,11 +4472,11 @@ public class ConnectivityService extends IConnectivityManager.Stub ++last; String key = "net.dns" + last; String value = dns.getHostAddress(); - SystemProperties.set(key, value); + mSystemProperties.set(key, value); } for (int i = last + 1; i <= mNumDnsEntries; ++i) { String key = "net.dns" + i; - SystemProperties.set(key, ""); + mSystemProperties.set(key, ""); } mNumDnsEntries = last; } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index c562cb95ee..70381e6860 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -23,7 +23,12 @@ import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.NetworkCapabilities.*; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; import android.app.NotificationManager; import android.app.PendingIntent; @@ -33,6 +38,7 @@ import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.ConnectivityManager.PacketKeepalive; @@ -76,12 +82,17 @@ import android.util.LogPrinter; import com.android.internal.util.WakeupMessage; import com.android.internal.util.test.BroadcastInterceptingContext; import com.android.internal.util.test.FakeSettingsProvider; +import com.android.server.connectivity.MockableSystemProperties; import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkMonitor; import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult; import com.android.server.net.NetworkPinner; import com.android.server.net.NetworkPolicyManagerInternal; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; + import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; @@ -134,8 +145,19 @@ public class ConnectivityServiceTest extends AndroidTestCase { private class MockContext extends BroadcastInterceptingContext { private final MockContentResolver mContentResolver; + @Spy private Resources mResources; + MockContext(Context base) { super(base); + + mResources = spy(base.getResources()); + when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)). + thenReturn(new String[] { + "wifi,1,1,1,-1,true", + "mobile,0,0,0,-1,true", + "mobile_mms,2,0,2,60000,true", + }); + mContentResolver = new MockContentResolver(); mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); } @@ -151,6 +173,11 @@ public class ConnectivityServiceTest extends AndroidTestCase { public ContentResolver getContentResolver() { return mContentResolver; } + + @Override + public Resources getResources() { + return mResources; + } } /** @@ -621,6 +648,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { private class WrappedConnectivityService extends ConnectivityService { public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker; private WrappedNetworkMonitor mLastCreatedNetworkMonitor; + private MockableSystemProperties mSystemProperties; public WrappedConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager, @@ -630,9 +658,13 @@ public class ConnectivityServiceTest extends AndroidTestCase { } @Override - protected int getDefaultTcpRwnd() { - // Prevent wrapped ConnectivityService from trying to write to SystemProperties. - return 0; + protected MockableSystemProperties getSystemProperties() { + // Minimal approach to overriding system properties: let most calls fall through to real + // device values, and only override ones values that are important to this test. + mSystemProperties = spy(new MockableSystemProperties()); + when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0); + when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false); + return mSystemProperties; } @Override @@ -805,6 +837,14 @@ public class ConnectivityServiceTest extends AndroidTestCase { return cv; } + public void testNetworkTypes() { + // Ensure that our mocks for the networkAttributes config variable work as expected. If they + // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types + // will fail. Failing here is much easier to debug. + assertTrue(mCm.isNetworkSupported(TYPE_WIFI)); + assertTrue(mCm.isNetworkSupported(TYPE_MOBILE)); + } + @SmallTest public void testLingering() throws Exception { verifyNoNetwork();