diff options
7 files changed, 189 insertions, 55 deletions
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index e96f4b0383cb..a4d7242086bf 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -278,6 +278,10 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { return mHandler; } + public Network network() { + return network; + } + // Functions for manipulating the requests satisfied by this network. // // These functions must only called on ConnectivityService's main thread. diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index d3a93542c740..8b886d6b3cff 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -20,7 +20,6 @@ import static android.net.CaptivePortal.APP_RETURN_DISMISSED; import static android.net.CaptivePortal.APP_RETURN_UNWANTED; import static android.net.CaptivePortal.APP_RETURN_WANTED_AS_IS; -import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; @@ -229,6 +228,8 @@ public class NetworkMonitor extends StateMachine { // Delay between reevaluations once a captive portal has been found. private static final int CAPTIVE_PORTAL_REEVALUATE_DELAY_MS = 10*60*1000; + private static final int NUM_VALIDATION_LOG_LINES = 20; + private final Context mContext; private final Handler mConnectivityServiceHandler; private final NetworkAgentInfo mNetworkAgentInfo; @@ -236,9 +237,15 @@ public class NetworkMonitor extends StateMachine { private final int mNetId; private final TelephonyManager mTelephonyManager; private final WifiManager mWifiManager; - private final AlarmManager mAlarmManager; private final NetworkRequest mDefaultRequest; private final IpConnectivityLog mMetricsLog; + private final NetworkMonitorSettings mSettings; + + // Configuration values for captive portal detection probes. + private final String mCaptivePortalUserAgent; + private final URL mCaptivePortalHttpsUrl; + private final URL mCaptivePortalHttpUrl; + private final URL[] mCaptivePortalFallbackUrls; @VisibleForTesting protected boolean mIsCaptivePortalCheckEnabled; @@ -262,40 +269,37 @@ public class NetworkMonitor extends StateMachine { private CustomIntentReceiver mLaunchCaptivePortalAppBroadcastReceiver = null; - private final LocalLog validationLogs = new LocalLog(20); // 20 lines + private final LocalLog validationLogs = new LocalLog(NUM_VALIDATION_LOG_LINES); private final Stopwatch mEvaluationTimer = new Stopwatch(); // This variable is set before transitioning to the mCaptivePortalState. private CaptivePortalProbeResult mLastPortalProbeResult = CaptivePortalProbeResult.FAILED; - // Configuration values for captive portal detection probes. - private final String mCaptivePortalUserAgent; - private final URL mCaptivePortalHttpsUrl; - private final URL mCaptivePortalHttpUrl; - private final URL[] mCaptivePortalFallbackUrls; private int mNextFallbackUrlIndex = 0; public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) { - this(context, handler, networkAgentInfo, defaultRequest, new IpConnectivityLog()); + this(context, handler, networkAgentInfo, defaultRequest, new IpConnectivityLog(), + NetworkMonitorSettings.DEFAULT); } @VisibleForTesting protected NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo, - NetworkRequest defaultRequest, IpConnectivityLog logger) { + NetworkRequest defaultRequest, IpConnectivityLog logger, + NetworkMonitorSettings settings) { // Add suffix indicating which NetworkMonitor we're talking about. super(TAG + networkAgentInfo.name()); mContext = context; mMetricsLog = logger; mConnectivityServiceHandler = handler; + mSettings = settings; mNetworkAgentInfo = networkAgentInfo; - mNetwork = new OneAddressPerFamilyNetwork(networkAgentInfo.network); + mNetwork = new OneAddressPerFamilyNetwork(networkAgentInfo.network()); mNetId = mNetwork.netId; mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); mDefaultRequest = defaultRequest; addState(mDefaultState); @@ -305,16 +309,12 @@ public class NetworkMonitor extends StateMachine { addState(mCaptivePortalState, mMaybeNotifyState); setInitialState(mDefaultState); - mIsCaptivePortalCheckEnabled = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.CAPTIVE_PORTAL_MODE, Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT) - != Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE; - mUseHttps = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.CAPTIVE_PORTAL_USE_HTTPS, 1) == 1; - - mCaptivePortalUserAgent = getCaptivePortalUserAgent(context); - mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl(context)); - mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(context)); - mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(context); + mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled(); + mUseHttps = getUseHttpsValidation(); + mCaptivePortalUserAgent = getCaptivePortalUserAgent(); + mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl()); + mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(settings, context)); + mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(); start(); } @@ -705,19 +705,42 @@ public class NetworkMonitor extends StateMachine { } } - private static String getCaptivePortalServerHttpsUrl(Context context) { - return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTPS_URL, DEFAULT_HTTPS_URL); + public boolean getIsCaptivePortalCheckEnabled() { + String symbol = Settings.Global.CAPTIVE_PORTAL_MODE; + int defaultValue = Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT; + int mode = mSettings.getSetting(mContext, symbol, defaultValue); + return mode != Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE; } + public boolean getUseHttpsValidation() { + return mSettings.getSetting(mContext, Settings.Global.CAPTIVE_PORTAL_USE_HTTPS, 1) == 1; + } + + public boolean getWifiScansAlwaysAvailableDisabled() { + return mSettings.getSetting(mContext, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 0; + } + + private String getCaptivePortalServerHttpsUrl() { + return mSettings.getSetting(mContext, + Settings.Global.CAPTIVE_PORTAL_HTTPS_URL, DEFAULT_HTTPS_URL); + } + + // Static for direct access by ConnectivityService public static String getCaptivePortalServerHttpUrl(Context context) { - return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL); + return getCaptivePortalServerHttpUrl(NetworkMonitorSettings.DEFAULT, context); + } + + public static String getCaptivePortalServerHttpUrl( + NetworkMonitorSettings settings, Context context) { + return settings.getSetting( + context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL); } - private URL[] makeCaptivePortalFallbackUrls(Context context) { + private URL[] makeCaptivePortalFallbackUrls() { String separator = ","; - String firstUrl = getSetting(context, + String firstUrl = mSettings.getSetting(mContext, Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, DEFAULT_FALLBACK_URL); - String joinedUrls = firstUrl + separator + getSetting(context, + String joinedUrls = firstUrl + separator + mSettings.getSetting(mContext, Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS, DEFAULT_OTHER_FALLBACK_URLS); List<URL> urls = new ArrayList<>(); for (String s : joinedUrls.split(separator)) { @@ -733,13 +756,9 @@ public class NetworkMonitor extends StateMachine { return urls.toArray(new URL[urls.size()]); } - private static String getCaptivePortalUserAgent(Context context) { - return getSetting(context, Settings.Global.CAPTIVE_PORTAL_USER_AGENT, DEFAULT_USER_AGENT); - } - - private static String getSetting(Context context, String symbol, String defaultValue) { - final String value = Settings.Global.getString(context.getContentResolver(), symbol); - return value != null ? value : defaultValue; + private String getCaptivePortalUserAgent() { + return mSettings.getSetting(mContext, + Settings.Global.CAPTIVE_PORTAL_USER_AGENT, DEFAULT_USER_AGENT); } private URL nextFallbackUrl() { @@ -1035,12 +1054,13 @@ public class NetworkMonitor extends StateMachine { */ private void sendNetworkConditionsBroadcast(boolean responseReceived, boolean isCaptivePortal, long requestTimestampMs, long responseTimestampMs) { - if (Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 0) { + if (getWifiScansAlwaysAvailableDisabled()) { return; } - if (systemReady == false) return; + if (!systemReady) { + return; + } Intent latencyBroadcast = new Intent(ACTION_NETWORK_CONDITIONS_MEASURED); switch (mNetworkAgentInfo.networkInfo.getType()) { @@ -1144,4 +1164,24 @@ public class NetworkMonitor extends StateMachine { ev.durationMs = durationMs; mMetricsLog.log(mNetId, transports, ev); } + + @VisibleForTesting + public interface NetworkMonitorSettings { + int getSetting(Context context, String symbol, int defaultValue); + String getSetting(Context context, String symbol, String defaultValue); + + static NetworkMonitorSettings DEFAULT = new DefaultNetworkMonitorSettings(); + } + + @VisibleForTesting + public static class DefaultNetworkMonitorSettings implements NetworkMonitorSettings { + public int getSetting(Context context, String symbol, int defaultValue) { + return Settings.Global.getInt(context.getContentResolver(), symbol, defaultValue); + } + + public String getSetting(Context context, String symbol, String defaultValue) { + final String value = Settings.Global.getString(context.getContentResolver(), symbol); + return value != null ? value : defaultValue; + } + } } diff --git a/tests/net/java/android/net/ip/IpManagerTest.java b/tests/net/java/android/net/ip/IpManagerTest.java index 541f91adf747..22d88fb70697 100644 --- a/tests/net/java/android/net/ip/IpManagerTest.java +++ b/tests/net/java/android/net/ip/IpManagerTest.java @@ -180,7 +180,8 @@ public class IpManagerTest { // Add N - 1 addresses for (int i = 0; i < lastAddr; i++) { mObserver.addressUpdated(iface, new LinkAddress(addresses[i])); - verify(mCb, timeout(100).times(1)).onLinkPropertiesChange(any()); + verify(mCb, timeout(100)).onLinkPropertiesChange(any()); + reset(mCb); } // Add Nth address diff --git a/tests/net/java/android/net/nsd/NsdManagerTest.java b/tests/net/java/android/net/nsd/NsdManagerTest.java index 9115378969ca..0a5a6aae6e9c 100644 --- a/tests/net/java/android/net/nsd/NsdManagerTest.java +++ b/tests/net/java/android/net/nsd/NsdManagerTest.java @@ -60,7 +60,7 @@ public class NsdManagerTest { NsdManager mManager; - long mTimeoutMs = 100; // non-final so that tests can adjust the value. + long mTimeoutMs = 200; // non-final so that tests can adjust the value. @Before public void setUp() throws Exception { @@ -74,7 +74,7 @@ public class NsdManagerTest { @After public void tearDown() throws Exception { - waitForIdleHandler(mServiceHandler, mTimeoutMs); + mServiceHandler.waitForIdle(mTimeoutMs); mServiceHandler.chan.disconnect(); mServiceHandler.stop(); if (mManager != null) { @@ -334,9 +334,10 @@ public class NsdManagerTest { } int verifyRequest(int expectedMessageType) { + mServiceHandler.waitForIdle(mTimeoutMs); verify(mServiceHandler, timeout(mTimeoutMs)).handleMessage(any()); reset(mServiceHandler); - Message received = mServiceHandler.lastMessage; + Message received = mServiceHandler.getLastMessage(); assertEquals(NsdManager.nameOf(expectedMessageType), NsdManager.nameOf(received.what)); return received.arg2; } @@ -347,31 +348,43 @@ public class NsdManagerTest { // Implements the server side of AsyncChannel connection protocol public static class MockServiceHandler extends Handler { - public Context mContext; + public final Context context; public AsyncChannel chan; - public volatile Message lastMessage; + public Message lastMessage; - MockServiceHandler(Looper looper, Context context) { - super(looper); - mContext = context; + MockServiceHandler(Looper l, Context c) { + super(l); + context = c; } - @Override - public void handleMessage(Message msg) { + synchronized Message getLastMessage() { + return lastMessage; + } + + synchronized void setLastMessage(Message msg) { lastMessage = obtainMessage(); lastMessage.copyFrom(msg); + } + + void waitForIdle(long timeoutMs) { + waitForIdleHandler(this, timeoutMs); + } + + @Override + public void handleMessage(Message msg) { + setLastMessage(msg); if (msg.what == AsyncChannel.CMD_CHANNEL_FULL_CONNECTION) { chan = new AsyncChannel(); - chan.connect(mContext, this, msg.replyTo); + chan.connect(context, this, msg.replyTo); chan.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED); } } - public void stop() { + void stop() { getLooper().quitSafely(); } - public static MockServiceHandler create(Context context) { + static MockServiceHandler create(Context context) { HandlerThread t = new HandlerThread("mock-service-handler"); t.start(); return new MockServiceHandler(t.getLooper(), context); diff --git a/tests/net/java/com/android/internal/util/TestUtils.java b/tests/net/java/com/android/internal/util/TestUtils.java index c9fa340dc8b5..6db01d343756 100644 --- a/tests/net/java/com/android/internal/util/TestUtils.java +++ b/tests/net/java/com/android/internal/util/TestUtils.java @@ -30,8 +30,7 @@ public final class TestUtils { * Block until the given Handler thread becomes idle, or until timeoutMs has passed. */ public static void waitForIdleHandler(HandlerThread handlerThread, long timeoutMs) { - // TODO: convert to getThreadHandler once it is available on aosp - waitForIdleLooper(handlerThread.getLooper(), timeoutMs); + waitForIdleHandler(handlerThread.getThreadHandler(), timeoutMs); } /** diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 8816d43ef8de..a8147380386f 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -683,7 +683,8 @@ public class ConnectivityServiceTest extends AndroidTestCase { public WrappedNetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest, IpConnectivityLog log) { - super(context, handler, networkAgentInfo, defaultRequest, log); + super(context, handler, networkAgentInfo, defaultRequest, log, + NetworkMonitor.NetworkMonitorSettings.DEFAULT); } @Override diff --git a/tests/net/java/com/android/server/connectivity/NetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/NetworkMonitorTest.java new file mode 100644 index 000000000000..27a897d175a2 --- /dev/null +++ b/tests/net/java/com/android/server/connectivity/NetworkMonitorTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.net.Network; +import android.net.NetworkRequest; +import android.net.metrics.IpConnectivityLog; +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import android.telephony.TelephonyManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class NetworkMonitorTest { + + static final int TEST_ID = 60; // should be less than min netid 100 + + @Mock Context mContext; + @Mock Handler mHandler; + @Mock IpConnectivityLog mLogger; + @Mock NetworkAgentInfo mAgent; + @Mock NetworkMonitor.NetworkMonitorSettings mSettings; + @Mock NetworkRequest mRequest; + @Mock TelephonyManager mTelephony; + @Mock WifiManager mWifi; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + when(mAgent.network()).thenReturn(new Network(TEST_ID)); + when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephony); + when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifi); + } + + NetworkMonitor makeMonitor() { + return new NetworkMonitor(mContext, mHandler, mAgent, mRequest, mLogger, mSettings); + } + + @Test + public void testCreatingNetworkMonitor() { + NetworkMonitor monitor = makeMonitor(); + } +} + |