Merge commit 'a19056c35d16ddb5a6c1d3343729701b8939f1e1' into nyc-mr1-dev-plus-aosp

* commit 'a19056c35d16ddb5a6c1d3343729701b8939f1e1': (35 commits)
  NetworkMonitor: send one DNS probe per web probe
  NetworkMonitor metrics: add first validation information
  APF: also drop any ICMPv6 RSs
  ConnectivityServiceTest: fix testAvoidBadWifiSettings
  Fix ConnectivityServiceTest testRequestBenchmark
  Switch over to new "time.android.com" NTP pool.
  Define API for metering network stats buckets.
  Refactored NetworkStatsServiceTest to use Mockito instead of EasyMock.
  Use @Ignore to explicitly disable a @Test method.
  Fixed NetworkStatsServiceTest and converted it to JUnit4.
  VPN network stat accounting changes.
  ConnectivityThread: use lazy holder idiom
  ConnectivityManager: use ConnectivityThread looper
  ConnectivityManager: a simpler CallbackHandler
  Indicate the NsdServiceInfo attributes are only filled in for a resolved service.
  Add a null check for the OnStartTetheringCallback.
  TokenBucket for rate-limiting and throttling
  IpConnectivityMetrics reads buffer size in settings
  CaptivePortalLogin: set mixed content policy to compatibility.
  Add IP conn metrics to dumpsys and bug reports
  ...
This commit is contained in:
The Android Automerger
2017-01-27 06:39:05 +00:00
12 changed files with 447 additions and 385 deletions

View File

@@ -2086,6 +2086,8 @@ public class ConnectivityManager {
@SystemApi @SystemApi
public void startTethering(int type, boolean showProvisioningUi, public void startTethering(int type, boolean showProvisioningUi,
final OnStartTetheringCallback callback, Handler handler) { final OnStartTetheringCallback callback, Handler handler) {
checkNotNull(callback, "OnStartTetheringCallback cannot be null.");
ResultReceiver wrappedCallback = new ResultReceiver(handler) { ResultReceiver wrappedCallback = new ResultReceiver(handler) {
@Override @Override
protected void onReceiveResult(int resultCode, Bundle resultData) { protected void onReceiveResult(int resultCode, Bundle resultData) {
@@ -2096,6 +2098,7 @@ public class ConnectivityManager {
} }
} }
}; };
try { try {
mService.startTethering(type, wrappedCallback, showProvisioningUi); mService.startTethering(type, wrappedCallback, showProvisioningUi);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -2599,7 +2602,8 @@ public class ConnectivityManager {
/** /**
* Called if no network is found in the given timeout time. If no timeout is given, * Called if no network is found in the given timeout time. If no timeout is given,
* this will not be called. * this will not be called. The associated {@link NetworkRequest} will have already
* been removed and released, as if {@link #unregisterNetworkCallback} had been called.
* @hide * @hide
*/ */
public void onUnavailable() {} public void onUnavailable() {}
@@ -2663,6 +2667,7 @@ public class ConnectivityManager {
public static final int CALLBACK_IP_CHANGED = BASE + 7; public static final int CALLBACK_IP_CHANGED = BASE + 7;
/** @hide */ /** @hide */
public static final int CALLBACK_RELEASED = BASE + 8; public static final int CALLBACK_RELEASED = BASE + 8;
// TODO: consider deleting CALLBACK_EXIT and shifting following enum codes down by 1.
/** @hide */ /** @hide */
public static final int CALLBACK_EXIT = BASE + 9; public static final int CALLBACK_EXIT = BASE + 9;
/** @hide obj = NetworkCapabilities, arg1 = seq number */ /** @hide obj = NetworkCapabilities, arg1 = seq number */
@@ -2672,25 +2677,38 @@ public class ConnectivityManager {
/** @hide */ /** @hide */
public static final int CALLBACK_RESUMED = BASE + 12; public static final int CALLBACK_RESUMED = BASE + 12;
/** @hide */
public static String getCallbackName(int whichCallback) {
switch (whichCallback) {
case CALLBACK_PRECHECK: return "CALLBACK_PRECHECK";
case CALLBACK_AVAILABLE: return "CALLBACK_AVAILABLE";
case CALLBACK_LOSING: return "CALLBACK_LOSING";
case CALLBACK_LOST: return "CALLBACK_LOST";
case CALLBACK_UNAVAIL: return "CALLBACK_UNAVAIL";
case CALLBACK_CAP_CHANGED: return "CALLBACK_CAP_CHANGED";
case CALLBACK_IP_CHANGED: return "CALLBACK_IP_CHANGED";
case CALLBACK_RELEASED: return "CALLBACK_RELEASED";
case CALLBACK_EXIT: return "CALLBACK_EXIT";
case EXPIRE_LEGACY_REQUEST: return "EXPIRE_LEGACY_REQUEST";
case CALLBACK_SUSPENDED: return "CALLBACK_SUSPENDED";
case CALLBACK_RESUMED: return "CALLBACK_RESUMED";
default:
return Integer.toString(whichCallback);
}
}
private class CallbackHandler extends Handler { private class CallbackHandler extends Handler {
private final HashMap<NetworkRequest, NetworkCallback>mCallbackMap;
private final AtomicInteger mRefCount;
private static final String TAG = "ConnectivityManager.CallbackHandler"; private static final String TAG = "ConnectivityManager.CallbackHandler";
private final ConnectivityManager mCm;
private static final boolean DBG = false; private static final boolean DBG = false;
CallbackHandler(Looper looper, HashMap<NetworkRequest, NetworkCallback>callbackMap, CallbackHandler(Looper looper) {
AtomicInteger refCount, ConnectivityManager cm) {
super(looper); super(looper);
mCallbackMap = callbackMap;
mRefCount = refCount;
mCm = cm;
} }
@Override @Override
public void handleMessage(Message message) { public void handleMessage(Message message) {
NetworkRequest request = (NetworkRequest) getObject(message, NetworkRequest.class); NetworkRequest request = getObject(message, NetworkRequest.class);
Network network = (Network) getObject(message, Network.class); Network network = getObject(message, Network.class);
if (DBG) { if (DBG) {
Log.d(TAG, whatToString(message.what) + " for network " + network); Log.d(TAG, whatToString(message.what) + " for network " + network);
} }
@@ -2733,9 +2751,7 @@ public class ConnectivityManager {
case CALLBACK_CAP_CHANGED: { case CALLBACK_CAP_CHANGED: {
NetworkCallback callback = getCallback(request, "CAP_CHANGED"); NetworkCallback callback = getCallback(request, "CAP_CHANGED");
if (callback != null) { if (callback != null) {
NetworkCapabilities cap = (NetworkCapabilities)getObject(message, NetworkCapabilities cap = getObject(message, NetworkCapabilities.class);
NetworkCapabilities.class);
callback.onCapabilitiesChanged(network, cap); callback.onCapabilitiesChanged(network, cap);
} }
break; break;
@@ -2743,9 +2759,7 @@ public class ConnectivityManager {
case CALLBACK_IP_CHANGED: { case CALLBACK_IP_CHANGED: {
NetworkCallback callback = getCallback(request, "IP_CHANGED"); NetworkCallback callback = getCallback(request, "IP_CHANGED");
if (callback != null) { if (callback != null) {
LinkProperties lp = (LinkProperties)getObject(message, LinkProperties lp = getObject(message, LinkProperties.class);
LinkProperties.class);
callback.onLinkPropertiesChanged(network, lp); callback.onLinkPropertiesChanged(network, lp);
} }
break; break;
@@ -2765,24 +2779,16 @@ public class ConnectivityManager {
break; break;
} }
case CALLBACK_RELEASED: { case CALLBACK_RELEASED: {
NetworkCallback callback = null; final NetworkCallback callback;
synchronized(mCallbackMap) { synchronized(sCallbacks) {
callback = mCallbackMap.remove(request); callback = sCallbacks.remove(request);
} }
if (callback != null) { if (callback == null) {
synchronized(mRefCount) {
if (mRefCount.decrementAndGet() == 0) {
getLooper().quit();
}
}
} else {
Log.e(TAG, "callback not found for RELEASED message"); Log.e(TAG, "callback not found for RELEASED message");
} }
break; break;
} }
case CALLBACK_EXIT: { case CALLBACK_EXIT: {
Log.d(TAG, "Listener quitting");
getLooper().quit();
break; break;
} }
case EXPIRE_LEGACY_REQUEST: { case EXPIRE_LEGACY_REQUEST: {
@@ -2792,14 +2798,14 @@ public class ConnectivityManager {
} }
} }
private Object getObject(Message msg, Class c) { private <T> T getObject(Message msg, Class<T> c) {
return msg.getData().getParcelable(c.getSimpleName()); return (T) msg.getData().getParcelable(c.getSimpleName());
} }
private NetworkCallback getCallback(NetworkRequest req, String name) { private NetworkCallback getCallback(NetworkRequest req, String name) {
NetworkCallback callback; NetworkCallback callback;
synchronized(mCallbackMap) { synchronized(sCallbacks) {
callback = mCallbackMap.get(req); callback = sCallbacks.get(req);
} }
if (callback == null) { if (callback == null) {
Log.e(TAG, "callback not found for " + name + " message"); Log.e(TAG, "callback not found for " + name + " message");
@@ -2808,63 +2814,56 @@ public class ConnectivityManager {
} }
} }
private void incCallbackHandlerRefCount() { private CallbackHandler getHandler() {
synchronized(sCallbackRefCount) { synchronized (sCallbacks) {
if (sCallbackRefCount.incrementAndGet() == 1) { if (sCallbackHandler == null) {
// TODO: switch this to ConnectivityThread sCallbackHandler = new CallbackHandler(ConnectivityThread.getInstanceLooper());
HandlerThread callbackThread = new HandlerThread("ConnectivityManager");
callbackThread.start();
sCallbackHandler = new CallbackHandler(callbackThread.getLooper(),
sNetworkCallback, sCallbackRefCount, this);
} }
return sCallbackHandler;
} }
} }
private void decCallbackHandlerRefCount() { static final HashMap<NetworkRequest, NetworkCallback> sCallbacks = new HashMap<>();
synchronized(sCallbackRefCount) { static CallbackHandler sCallbackHandler;
if (sCallbackRefCount.decrementAndGet() == 0) {
sCallbackHandler.obtainMessage(CALLBACK_EXIT).sendToTarget();
sCallbackHandler = null;
}
}
}
static final HashMap<NetworkRequest, NetworkCallback> sNetworkCallback =
new HashMap<NetworkRequest, NetworkCallback>();
static final AtomicInteger sCallbackRefCount = new AtomicInteger(0);
static CallbackHandler sCallbackHandler = null;
private final static int LISTEN = 1; private final static int LISTEN = 1;
private final static int REQUEST = 2; private final static int REQUEST = 2;
private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, private NetworkRequest sendRequestForNetwork(NetworkCapabilities need,
NetworkCallback networkCallback, int timeoutSec, int action, NetworkCallback callback, int timeoutMs, int action, int legacyType) {
int legacyType) { return sendRequestForNetwork(need, callback, getHandler(), timeoutMs, action, legacyType);
if (networkCallback == null) { }
private NetworkRequest sendRequestForNetwork(NetworkCapabilities need,
NetworkCallback callback, Handler handler, int timeoutMs, int action, int legacyType) {
if (callback == null) {
throw new IllegalArgumentException("null NetworkCallback"); throw new IllegalArgumentException("null NetworkCallback");
} }
if (need == null && action != REQUEST) { if (need == null && action != REQUEST) {
throw new IllegalArgumentException("null NetworkCapabilities"); throw new IllegalArgumentException("null NetworkCapabilities");
} }
// TODO: throw an exception if callback.networkRequest is not null.
// http://b/20701525
final NetworkRequest request;
try { try {
incCallbackHandlerRefCount(); synchronized(sCallbacks) {
synchronized(sNetworkCallback) { Messenger messenger = new Messenger(handler);
Binder binder = new Binder();
if (action == LISTEN) { if (action == LISTEN) {
networkCallback.networkRequest = mService.listenForNetwork(need, request = mService.listenForNetwork(need, messenger, binder);
new Messenger(sCallbackHandler), new Binder());
} else { } else {
networkCallback.networkRequest = mService.requestNetwork(need, request = mService.requestNetwork(
new Messenger(sCallbackHandler), timeoutSec, new Binder(), legacyType); need, messenger, timeoutMs, binder, legacyType);
} }
if (networkCallback.networkRequest != null) { if (request != null) {
sNetworkCallback.put(networkCallback.networkRequest, networkCallback); sCallbacks.put(request, callback);
} }
callback.networkRequest = request;
} }
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
if (networkCallback.networkRequest == null) decCallbackHandlerRefCount(); return request;
return networkCallback.networkRequest;
} }
/** /**

View File

@@ -27,25 +27,30 @@ import android.os.Looper;
* @hide * @hide
*/ */
public final class ConnectivityThread extends HandlerThread { public final class ConnectivityThread extends HandlerThread {
private static ConnectivityThread sInstance;
// A class implementing the lazy holder idiom: the unique static instance
// of ConnectivityThread is instantiated in a thread-safe way (guaranteed by
// the language specs) the first time that Singleton is referenced in get()
// or getInstanceLooper().
private static class Singleton {
private static final ConnectivityThread INSTANCE = createInstance();
}
private ConnectivityThread() { private ConnectivityThread() {
super("ConnectivityThread"); super("ConnectivityThread");
} }
private static synchronized ConnectivityThread getInstance() { private static ConnectivityThread createInstance() {
if (sInstance == null) { ConnectivityThread t = new ConnectivityThread();
sInstance = new ConnectivityThread(); t.start();
sInstance.start(); return t;
}
return sInstance;
} }
public static ConnectivityThread get() { public static ConnectivityThread get() {
return getInstance(); return Singleton.INSTANCE;
} }
public static Looper getInstanceLooper() { public static Looper getInstanceLooper() {
return getInstance().getLooper(); return Singleton.INSTANCE.getLooper();
} }
} }

View File

@@ -1804,11 +1804,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void updateMtu(LinkProperties newLp, LinkProperties oldLp) { private void updateMtu(LinkProperties newLp, LinkProperties oldLp) {
final String iface = newLp.getInterfaceName(); final String iface = newLp.getInterfaceName();
final int mtu = newLp.getMtu(); final int mtu = newLp.getMtu();
if (oldLp == null && mtu == 0) {
// Silently ignore unset MTU value.
return;
}
if (oldLp != null && newLp.isIdenticalMtu(oldLp)) { if (oldLp != null && newLp.isIdenticalMtu(oldLp)) {
if (VDBG) log("identical MTU - not setting"); if (VDBG) log("identical MTU - not setting");
return; return;
} }
if (LinkProperties.isValidMtu(mtu, newLp.hasGlobalIPv6Address()) == false) { if (LinkProperties.isValidMtu(mtu, newLp.hasGlobalIPv6Address()) == false) {
if (mtu != 0) loge("Unexpected mtu value: " + mtu + ", " + iface); if (mtu != 0) loge("Unexpected mtu value: " + mtu + ", " + iface);
return; return;
@@ -2602,14 +2605,28 @@ public class ConnectivityService extends IConnectivityManager.Stub
"request NetworkCapabilities", ConnectivityManager.CALLBACK_CAP_CHANGED); "request NetworkCapabilities", ConnectivityManager.CALLBACK_CAP_CHANGED);
} }
private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) {
if (mNetworkRequests.get(nri.request) != null && mNetworkForRequestId.get(
nri.request.requestId) == null) {
handleRemoveNetworkRequest(nri, ConnectivityManager.CALLBACK_UNAVAIL);
}
}
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) { private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
final NetworkRequestInfo nri = getNriForAppRequest( final NetworkRequestInfo nri = getNriForAppRequest(
request, callingUid, "release NetworkRequest"); request, callingUid, "release NetworkRequest");
if (nri == null) return; if (nri != null) {
handleRemoveNetworkRequest(nri, ConnectivityManager.CALLBACK_RELEASED);
}
}
if (VDBG || (DBG && nri.request.isRequest())) log("releasing " + request); private void handleRemoveNetworkRequest(final NetworkRequestInfo nri, final int whichCallback) {
final String logCallbackType = ConnectivityManager.getCallbackName(whichCallback);
if (VDBG || (DBG && nri.request.isRequest())) {
log("releasing " + nri.request + " (" + logCallbackType + ")");
}
nri.unlinkDeathRecipient(); nri.unlinkDeathRecipient();
mNetworkRequests.remove(request); mNetworkRequests.remove(nri.request);
synchronized (mUidToNetworkRequestCount) { synchronized (mUidToNetworkRequestCount) {
int requests = mUidToNetworkRequestCount.get(nri.mUid, 0); int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
if (requests < 1) { if (requests < 1) {
@@ -2703,7 +2720,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
} }
} }
callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED, 0); callCallbackForRequest(nri, null, whichCallback, 0);
} }
@Override @Override
@@ -2940,6 +2957,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
handleRegisterNetworkRequestWithIntent(msg); handleRegisterNetworkRequestWithIntent(msg);
break; break;
} }
case EVENT_TIMEOUT_NETWORK_REQUEST: {
NetworkRequestInfo nri = (NetworkRequestInfo) msg.obj;
handleTimedOutNetworkRequest(nri);
break;
}
case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: { case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: {
handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1); handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1);
break; break;
@@ -5297,6 +5319,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// notify only this one new request of the current state // notify only this one new request of the current state
protected void notifyNetworkCallback(NetworkAgentInfo nai, NetworkRequestInfo nri) { protected void notifyNetworkCallback(NetworkAgentInfo nai, NetworkRequestInfo nri) {
int notifyType = ConnectivityManager.CALLBACK_AVAILABLE; int notifyType = ConnectivityManager.CALLBACK_AVAILABLE;
mHandler.removeMessages(EVENT_TIMEOUT_NETWORK_REQUEST, nri);
if (nri.mPendingIntent == null) { if (nri.mPendingIntent == null) {
callCallbackForRequest(nri, nai, notifyType, 0); callCallbackForRequest(nri, nai, notifyType, 0);
} else { } else {

View File

@@ -24,6 +24,7 @@ import android.os.Binder;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.LargeTest;
import com.android.server.net.BaseNetworkObserver; import com.android.server.net.BaseNetworkObserver;
import com.android.internal.util.test.BroadcastInterceptingContext;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;

View File

@@ -40,21 +40,21 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS; import static android.text.format.DateUtils.WEEK_IN_MILLIS;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL; import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
import static org.easymock.EasyMock.anyInt;
import static org.easymock.EasyMock.anyLong; import static org.junit.Assert.assertEquals;
import static org.easymock.EasyMock.anyObject; import static org.junit.Assert.assertNotNull;
import static org.easymock.EasyMock.capture; import static org.junit.Assert.assertNull;
import static org.easymock.EasyMock.createMock; import static org.junit.Assert.assertTrue;
import static org.easymock.EasyMock.eq; import static org.junit.Assert.fail;
import static org.easymock.EasyMock.expect; import static org.mockito.Matchers.any;
import static org.easymock.EasyMock.expectLastCall; import static org.mockito.Matchers.anyInt;
import static org.easymock.EasyMock.isA; import static org.mockito.Matchers.anyLong;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.IAlarmListener;
import android.app.IAlarmManager;
import android.app.PendingIntent;
import android.app.usage.NetworkStatsManager; import android.app.usage.NetworkStatsManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -63,6 +63,7 @@ import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver; import android.net.INetworkManagementEventObserver;
import android.net.INetworkStatsSession; import android.net.INetworkStatsSession;
import android.net.LinkProperties; import android.net.LinkProperties;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState; import android.net.NetworkInfo.DetailedState;
import android.net.NetworkState; import android.net.NetworkState;
@@ -80,23 +81,28 @@ import android.os.MessageQueue;
import android.os.MessageQueue.IdleHandler; import android.os.MessageQueue.IdleHandler;
import android.os.Message; import android.os.Message;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.WorkSource; import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.Suppress;
import android.util.TrustedTime; import android.util.TrustedTime;
import com.android.internal.net.VpnInfo; import com.android.internal.net.VpnInfo;
import com.android.server.BroadcastInterceptingContext; import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.server.net.NetworkStatsService; import com.android.server.net.NetworkStatsService;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings; import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config; import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config;
import libcore.io.IoUtils; import libcore.io.IoUtils;
import org.easymock.Capture; import org.junit.After;
import org.easymock.EasyMock; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
@@ -106,11 +112,11 @@ import java.util.List;
/** /**
* Tests for {@link NetworkStatsService}. * Tests for {@link NetworkStatsService}.
* *
* TODO: This test is really brittle, largely due to overly-strict use of Easymock. * TODO: This test used to be really brittle because it used Easymock - it uses Mockito now, but
* Rewrite w/ Mockito. * still uses the Easymock structure, which could be simplified.
*/ */
@LargeTest @RunWith(AndroidJUnit4.class)
public class NetworkStatsServiceTest extends AndroidTestCase { public class NetworkStatsServiceTest {
private static final String TAG = "NetworkStatsServiceTest"; private static final String TAG = "NetworkStatsServiceTest";
private static final String TEST_IFACE = "test0"; private static final String TEST_IFACE = "test0";
@@ -137,10 +143,12 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
private BroadcastInterceptingContext mServiceContext; private BroadcastInterceptingContext mServiceContext;
private File mStatsDir; private File mStatsDir;
private INetworkManagementService mNetManager; private @Mock INetworkManagementService mNetManager;
private TrustedTime mTime; private @Mock TrustedTime mTime;
private NetworkStatsSettings mSettings; private @Mock NetworkStatsSettings mSettings;
private IConnectivityManager mConnManager; private @Mock IConnectivityManager mConnManager;
private @Mock IBinder mBinder;
private @Mock AlarmManager mAlarmManager;
private IdleableHandlerThread mHandlerThread; private IdleableHandlerThread mHandlerThread;
private Handler mHandler; private Handler mHandler;
@@ -148,32 +156,24 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
private INetworkStatsSession mSession; private INetworkStatsSession mSession;
private INetworkManagementEventObserver mNetworkObserver; private INetworkManagementEventObserver mNetworkObserver;
@Override @Before
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); MockitoAnnotations.initMocks(this);
final Context context = InstrumentationRegistry.getContext();
mServiceContext = new BroadcastInterceptingContext(getContext()); mServiceContext = new BroadcastInterceptingContext(context);
mStatsDir = getContext().getFilesDir(); mStatsDir = context.getFilesDir();
if (mStatsDir.exists()) { if (mStatsDir.exists()) {
IoUtils.deleteContents(mStatsDir); IoUtils.deleteContents(mStatsDir);
} }
mNetManager = createMock(INetworkManagementService.class);
// TODO: Mock AlarmManager when migrating this test to Mockito.
AlarmManager alarmManager = (AlarmManager) mServiceContext
.getSystemService(Context.ALARM_SERVICE);
mTime = createMock(TrustedTime.class);
mSettings = createMock(NetworkStatsSettings.class);
mConnManager = createMock(IConnectivityManager.class);
PowerManager powerManager = (PowerManager) mServiceContext.getSystemService( PowerManager powerManager = (PowerManager) mServiceContext.getSystemService(
Context.POWER_SERVICE); Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = PowerManager.WakeLock wakeLock =
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mService = new NetworkStatsService( mService = new NetworkStatsService(
mServiceContext, mNetManager, alarmManager, wakeLock, mTime, mServiceContext, mNetManager, mAlarmManager, wakeLock, mTime,
TelephonyManager.getDefault(), mSettings, new NetworkStatsObservers(), TelephonyManager.getDefault(), mSettings, new NetworkStatsObservers(),
mStatsDir, getBaseDir(mStatsDir)); mStatsDir, getBaseDir(mStatsDir));
mHandlerThread = new IdleableHandlerThread("HandlerThread"); mHandlerThread = new IdleableHandlerThread("HandlerThread");
@@ -190,22 +190,20 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectSystemReady(); expectSystemReady();
// catch INetworkManagementEventObserver during systemReady()
final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
INetworkManagementEventObserver>();
mNetManager.registerObserver(capture(networkObserver));
expectLastCall().atLeastOnce();
replay();
mService.systemReady(); mService.systemReady();
mSession = mService.openSession(); mSession = mService.openSession();
verifyAndReset(); assertNotNull("openSession() failed", mSession);
// catch INetworkManagementEventObserver during systemReady()
ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
verify(mNetManager).registerObserver(networkObserver.capture());
mNetworkObserver = networkObserver.getValue(); mNetworkObserver = networkObserver.getValue();
} }
@Override @After
public void tearDown() throws Exception { public void tearDown() throws Exception {
IoUtils.deleteContents(mStatsDir); IoUtils.deleteContents(mStatsDir);
@@ -219,10 +217,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
mSession.close(); mSession.close();
mService = null; mService = null;
super.tearDown();
} }
@Test
public void testNetworkStatsWifi() throws Exception { public void testNetworkStatsWifi() throws Exception {
// pretend that wifi network comes online; service should ask about full // pretend that wifi network comes online; service should ask about full
// network state, and poll any existing interfaces before updating. // network state, and poll any existing interfaces before updating.
@@ -231,15 +228,13 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
// verify service has empty history for wifi // verify service has empty history for wifi
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
verifyAndReset();
// modify some number on wifi, and trigger poll event // modify some number on wifi, and trigger poll event
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -248,14 +243,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L)); .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L));
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0);
verifyAndReset();
// and bump forward again, with counters going higher. this is // and bump forward again, with counters going higher. this is
// important, since polling should correctly subtract last snapshot. // important, since polling should correctly subtract last snapshot.
@@ -265,17 +257,14 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 4096L, 4L, 8192L, 8L)); .addIfaceValues(TEST_IFACE, 4096L, 4L, 8192L, 8L));
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0); assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0);
verifyAndReset();
} }
@Test
public void testStatsRebootPersist() throws Exception { public void testStatsRebootPersist() throws Exception {
assertStatsFilesExist(false); assertStatsFilesExist(false);
@@ -286,15 +275,13 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
// verify service has empty history for wifi // verify service has empty history for wifi
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
verifyAndReset();
// modify some number on wifi, and trigger poll event // modify some number on wifi, and trigger poll event
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -308,14 +295,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L) .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L)); .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L));
expectNetworkStatsPoll();
mService.setUidForeground(UID_RED, false); mService.setUidForeground(UID_RED, false);
mService.incrementOperationCount(UID_RED, 0xFAAD, 4); mService.incrementOperationCount(UID_RED, 0xFAAD, 4);
mService.setUidForeground(UID_RED, true); mService.setUidForeground(UID_RED, true);
mService.incrementOperationCount(UID_RED, 0xFAAD, 6); mService.incrementOperationCount(UID_RED, 0xFAAD, 6);
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
@@ -325,16 +309,13 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L, assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L,
6); 6);
assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0); assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0);
verifyAndReset();
// graceful shutdown system, which should trigger persist of stats, and // graceful shutdown system, which should trigger persist of stats, and
// clear any values in memory. // clear any values in memory.
expectCurrentTime(); expectCurrentTime();
expectDefaultSettings(); expectDefaultSettings();
replay();
mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SHUTDOWN)); mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SHUTDOWN));
verifyAndReset();
assertStatsFilesExist(true); assertStatsFilesExist(true);
// boot through serviceReady() again // boot through serviceReady() again
@@ -343,17 +324,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectSystemReady(); expectSystemReady();
// catch INetworkManagementEventObserver during systemReady()
final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
INetworkManagementEventObserver>();
mNetManager.registerObserver(capture(networkObserver));
expectLastCall().atLeastOnce();
replay();
mService.systemReady(); mService.systemReady();
mNetworkObserver = networkObserver.getValue();
// after systemReady(), we should have historical stats loaded again // after systemReady(), we should have historical stats loaded again
assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0);
assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10); assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10);
@@ -361,12 +333,12 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L, assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L,
6); 6);
assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0); assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0);
verifyAndReset();
} }
// TODO: simulate reboot to test bucket resize // TODO: simulate reboot to test bucket resize
@Suppress @Test
@Ignore
public void testStatsBucketResize() throws Exception { public void testStatsBucketResize() throws Exception {
NetworkStatsHistory history = null; NetworkStatsHistory history = null;
@@ -379,12 +351,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
verifyAndReset();
// modify some number on wifi, and trigger poll event // modify some number on wifi, and trigger poll event
incrementCurrentTime(2 * HOUR_IN_MILLIS); incrementCurrentTime(2 * HOUR_IN_MILLIS);
@@ -393,9 +363,6 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 512L, 4L, 512L, 4L)); .addIfaceValues(TEST_IFACE, 512L, 4L, 512L, 4L));
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
@@ -403,7 +370,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0);
assertEquals(HOUR_IN_MILLIS, history.getBucketDuration()); assertEquals(HOUR_IN_MILLIS, history.getBucketDuration());
assertEquals(2, history.size()); assertEquals(2, history.size());
verifyAndReset();
// now change bucket duration setting and trigger another poll with // now change bucket duration setting and trigger another poll with
// exact same values, which should resize existing buckets. // exact same values, which should resize existing buckets.
@@ -411,9 +378,6 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS); expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS);
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify identical stats, but spread across 4 buckets now // verify identical stats, but spread across 4 buckets now
@@ -421,10 +385,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0);
assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration()); assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration());
assertEquals(4, history.size()); assertEquals(4, history.size());
verifyAndReset();
} }
@Test
public void testUidStatsAcrossNetworks() throws Exception { public void testUidStatsAcrossNetworks() throws Exception {
// pretend first mobile network comes online // pretend first mobile network comes online
expectCurrentTime(); expectCurrentTime();
@@ -432,12 +396,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildMobile3gState(IMSI_1)); expectNetworkState(buildMobile3gState(IMSI_1));
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
verifyAndReset();
// create some traffic on first network // create some traffic on first network
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -449,11 +411,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
expectNetworkStatsPoll();
mService.incrementOperationCount(UID_RED, 0xF00D, 10); mService.incrementOperationCount(UID_RED, 0xF00D, 10);
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
@@ -461,7 +420,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 512L, 4L, 10); assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 512L, 4L, 10);
assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 4L, 0L, 0L, 0); assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 4L, 0L, 0L, 0);
verifyAndReset();
// now switch networks; this also tests that we're okay with interfaces // now switch networks; this also tests that we're okay with interfaces
// disappearing, to verify we don't count backwards. // disappearing, to verify we don't count backwards.
@@ -475,13 +434,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
verifyAndReset();
// create traffic on second network // create traffic on second network
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -494,11 +451,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L)); .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L));
expectNetworkStatsPoll();
mService.incrementOperationCount(UID_BLUE, 0xFAAD, 10); mService.incrementOperationCount(UID_BLUE, 0xFAAD, 10);
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify original history still intact // verify original history still intact
@@ -511,10 +465,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
assertNetworkTotal(sTemplateImsi2, 128L, 1L, 1024L, 8L, 0); assertNetworkTotal(sTemplateImsi2, 128L, 1L, 1024L, 8L, 0);
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1L, 1024L, 8L, 10); assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1L, 1024L, 8L, 10);
verifyAndReset();
} }
@Test
public void testUidRemovedIsMoved() throws Exception { public void testUidRemovedIsMoved() throws Exception {
// pretend that network comes online // pretend that network comes online
expectCurrentTime(); expectCurrentTime();
@@ -522,12 +476,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
verifyAndReset();
// create some traffic // create some traffic
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -540,11 +492,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
.addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); .addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
expectNetworkStatsPoll();
mService.incrementOperationCount(UID_RED, 0xFAAD, 10); mService.incrementOperationCount(UID_RED, 0xFAAD, 10);
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
@@ -552,7 +501,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
assertUidTotal(sTemplateWifi, UID_RED, 16L, 1L, 16L, 1L, 10); assertUidTotal(sTemplateWifi, UID_RED, 16L, 1L, 16L, 1L, 10);
assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 258L, 512L, 32L, 0); assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 258L, 512L, 32L, 0);
assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 0); assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 0);
verifyAndReset();
// now pretend two UIDs are uninstalled, which should migrate stats to // now pretend two UIDs are uninstalled, which should migrate stats to
// special "removed" bucket. // special "removed" bucket.
@@ -565,9 +514,6 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
.addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); .addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
expectNetworkStatsPoll();
replay();
final Intent intent = new Intent(ACTION_UID_REMOVED); final Intent intent = new Intent(ACTION_UID_REMOVED);
intent.putExtra(EXTRA_UID, UID_BLUE); intent.putExtra(EXTRA_UID, UID_BLUE);
mServiceContext.sendBroadcast(intent); mServiceContext.sendBroadcast(intent);
@@ -581,10 +527,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L, 0L, 0L, 0); assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L, 0L, 0L, 0);
assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 0); assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 0);
assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 259L, 528L, 33L, 10); assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 259L, 528L, 33L, 10);
verifyAndReset();
} }
@Test
public void testUid3g4gCombinedByTemplate() throws Exception { public void testUid3g4gCombinedByTemplate() throws Exception {
// pretend that network comes online // pretend that network comes online
expectCurrentTime(); expectCurrentTime();
@@ -592,12 +538,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildMobile3gState(IMSI_1)); expectNetworkState(buildMobile3gState(IMSI_1));
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
verifyAndReset();
// create some traffic // create some traffic
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -607,16 +551,13 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)); .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
expectNetworkStatsPoll();
mService.incrementOperationCount(UID_RED, 0xF00D, 5); mService.incrementOperationCount(UID_RED, 0xF00D, 5);
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 8L, 1024L, 8L, 5); assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 8L, 1024L, 8L, 5);
verifyAndReset();
// now switch over to 4g network // now switch over to 4g network
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -627,13 +568,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)); .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
verifyAndReset();
// create traffic on second network // create traffic on second network
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -645,19 +584,15 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
.addValues(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L) .addValues(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
.addValues(TEST_IFACE2, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L)); .addValues(TEST_IFACE2, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L));
expectNetworkStatsPoll();
mService.incrementOperationCount(UID_RED, 0xFAAD, 5); mService.incrementOperationCount(UID_RED, 0xFAAD, 5);
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify that ALL_MOBILE template combines both // verify that ALL_MOBILE template combines both
assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 1280L, 10L, 10); assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 1280L, 10L, 10);
verifyAndReset();
} }
@Test
public void testSummaryForAllUid() throws Exception { public void testSummaryForAllUid() throws Exception {
// pretend that network comes online // pretend that network comes online
expectCurrentTime(); expectCurrentTime();
@@ -665,12 +600,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
verifyAndReset();
// create some traffic for two apps // create some traffic for two apps
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -681,17 +614,14 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L)); .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L));
expectNetworkStatsPoll();
mService.incrementOperationCount(UID_RED, 0xF00D, 1); mService.incrementOperationCount(UID_RED, 0xF00D, 1);
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
assertUidTotal(sTemplateWifi, UID_RED, 50L, 5L, 50L, 5L, 1); assertUidTotal(sTemplateWifi, UID_RED, 50L, 5L, 50L, 5L, 1);
assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 8L, 512L, 4L, 0); assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 8L, 512L, 4L, 0);
verifyAndReset();
// now create more traffic in next hour, but only for one app // now create more traffic in next hour, but only for one app
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -702,9 +632,6 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L)); .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L));
expectNetworkStatsPoll();
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// first verify entire history present // first verify entire history present
@@ -725,10 +652,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
assertEquals(1, stats.size()); assertEquals(1, stats.size());
assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L,
512L, 4L, 0); 512L, 4L, 0);
verifyAndReset();
} }
@Test
public void testForegroundBackground() throws Exception { public void testForegroundBackground() throws Exception {
// pretend that network comes online // pretend that network comes online
expectCurrentTime(); expectCurrentTime();
@@ -736,12 +662,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
verifyAndReset();
// create some initial traffic // create some initial traffic
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -751,16 +675,13 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)); .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L));
expectNetworkStatsPoll();
mService.incrementOperationCount(UID_RED, 0xF00D, 1); mService.incrementOperationCount(UID_RED, 0xF00D, 1);
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
assertUidTotal(sTemplateWifi, UID_RED, 128L, 2L, 128L, 2L, 1); assertUidTotal(sTemplateWifi, UID_RED, 128L, 2L, 128L, 2L, 1);
verifyAndReset();
// now switch to foreground // now switch to foreground
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -772,12 +693,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L)); .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L));
expectNetworkStatsPoll();
mService.setUidForeground(UID_RED, true); mService.setUidForeground(UID_RED, true);
mService.incrementOperationCount(UID_RED, 0xFAAD, 1); mService.incrementOperationCount(UID_RED, 0xFAAD, 1);
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// test that we combined correctly // test that we combined correctly
@@ -795,10 +713,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
32L, 2L, 1); 32L, 2L, 1);
assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, ROAMING_NO, 1L, 1L, 1L, assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, ROAMING_NO, 1L, 1L, 1L,
1L, 1); 1L, 1);
verifyAndReset();
} }
@Test
public void testRoaming() throws Exception { public void testRoaming() throws Exception {
// pretend that network comes online // pretend that network comes online
expectCurrentTime(); expectCurrentTime();
@@ -806,12 +723,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildMobile3gState(IMSI_1, true /* isRoaming */)); expectNetworkState(buildMobile3gState(IMSI_1, true /* isRoaming */));
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
verifyAndReset();
// Create some traffic // Create some traffic
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -826,9 +741,6 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
128L, 2L, 0L) 128L, 2L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L, .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L,
1L, 0L)); 1L, 0L));
expectNetworkStatsPoll();
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
@@ -842,10 +754,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
128L, 2L, 0); 128L, 2L, 0);
assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES, 64L, 1L, 64L, assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES, 64L, 1L, 64L,
1L, 0); 1L, 0);
verifyAndReset();
} }
@Test
public void testTethering() throws Exception { public void testTethering() throws Exception {
// pretend first mobile network comes online // pretend first mobile network comes online
expectCurrentTime(); expectCurrentTime();
@@ -853,12 +764,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildMobile3gState(IMSI_1)); expectNetworkState(buildMobile3gState(IMSI_1));
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
verifyAndReset();
// create some tethering traffic // create some tethering traffic
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
@@ -874,19 +783,16 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L, 0L); .addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L, 0L);
expectNetworkStatsUidDetail(uidStats, tetherIfacePairs, tetherStats); expectNetworkStatsUidDetail(uidStats, tetherIfacePairs, tetherStats);
expectNetworkStatsPoll();
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0); assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0);
assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 0); assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 0);
assertUidTotal(sTemplateImsi1, UID_TETHERING, 1920L, 14L, 384L, 2L, 0); assertUidTotal(sTemplateImsi1, UID_TETHERING, 1920L, 14L, 384L, 2L, 0);
verifyAndReset();
} }
@Test
public void testRegisterUsageCallback() throws Exception { public void testRegisterUsageCallback() throws Exception {
// pretend that wifi network comes online; service should ask about full // pretend that wifi network comes online; service should ask about full
// network state, and poll any existing interfaces before updating. // network state, and poll any existing interfaces before updating.
@@ -895,16 +801,12 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
expectBandwidthControlCheck(); expectBandwidthControlCheck();
replay();
mService.forceUpdateIfaces(); mService.forceUpdateIfaces();
// verify service has empty history for wifi // verify service has empty history for wifi
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
verifyAndReset();
String callingPackage = "the.calling.package"; String callingPackage = "the.calling.package";
long thresholdInBytes = 1L; // very small; should be overriden by framework long thresholdInBytes = 1L; // very small; should be overriden by framework
DataUsageRequest inputRequest = new DataUsageRequest( DataUsageRequest inputRequest = new DataUsageRequest(
@@ -915,23 +817,18 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
LatchedHandler latchedHandler = new LatchedHandler(Looper.getMainLooper(), cv); LatchedHandler latchedHandler = new LatchedHandler(Looper.getMainLooper(), cv);
Messenger messenger = new Messenger(latchedHandler); Messenger messenger = new Messenger(latchedHandler);
// Allow binder to connect
IBinder mockBinder = createMock(IBinder.class);
mockBinder.linkToDeath((IBinder.DeathRecipient) anyObject(), anyInt());
EasyMock.replay(mockBinder);
// Force poll // Force poll
expectCurrentTime(); expectCurrentTime();
expectDefaultSettings(); expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay();
// Register and verify request and that binder was called // Register and verify request and that binder was called
DataUsageRequest request = DataUsageRequest request =
mService.registerUsageCallback(callingPackage, inputRequest, mService.registerUsageCallback(callingPackage, inputRequest,
messenger, mockBinder); messenger, mBinder);
assertTrue(request.requestId > 0); assertTrue(request.requestId > 0);
assertTrue(Objects.equals(sTemplateWifi, request.template)); assertTrue(Objects.equals(sTemplateWifi, request.template));
long minThresholdInBytes = 2 * 1024 * 1024; // 2 MB long minThresholdInBytes = 2 * 1024 * 1024; // 2 MB
@@ -941,11 +838,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
mHandler.sendMessage(mHandler.obtainMessage(-1)); mHandler.sendMessage(mHandler.obtainMessage(-1));
mHandlerThread.waitForIdle(WAIT_TIMEOUT); mHandlerThread.waitForIdle(WAIT_TIMEOUT);
verifyAndReset();
// Make sure that the caller binder gets connected // Make sure that the caller binder gets connected
EasyMock.verify(mockBinder); verify(mBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
EasyMock.reset(mockBinder);
// modify some number on wifi, and trigger poll event // modify some number on wifi, and trigger poll event
// not enough traffic to call data usage callback // not enough traffic to call data usage callback
@@ -955,13 +852,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L)); .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L));
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
verifyAndReset();
assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0);
// make sure callback has not being called // make sure callback has not being called
@@ -975,14 +868,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 4096000L, 4L, 8192000L, 8L)); .addIfaceValues(TEST_IFACE, 4096000L, 4L, 8192000L, 8L));
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay();
forcePollAndWaitForIdle(); forcePollAndWaitForIdle();
// verify service recorded history // verify service recorded history
assertNetworkTotal(sTemplateWifi, 4096000L, 4L, 8192000L, 8L, 0); assertNetworkTotal(sTemplateWifi, 4096000L, 4L, 8192000L, 8L, 0);
verifyAndReset();
// Wait for the caller to ack receipt of CALLBACK_LIMIT_REACHED // Wait for the caller to ack receipt of CALLBACK_LIMIT_REACHED
assertTrue(cv.block(WAIT_TIMEOUT)); assertTrue(cv.block(WAIT_TIMEOUT));
@@ -990,9 +880,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
cv.close(); cv.close();
// Allow binder to disconnect // Allow binder to disconnect
expect(mockBinder.unlinkToDeath((IBinder.DeathRecipient) anyObject(), anyInt())) when(mBinder.unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt())).thenReturn(true);
.andReturn(true);
EasyMock.replay(mockBinder);
// Unregister request // Unregister request
mService.unregisterUsageRequest(request); mService.unregisterUsageRequest(request);
@@ -1002,9 +890,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
assertEquals(NetworkStatsManager.CALLBACK_RELEASED, latchedHandler.mLastMessageType); assertEquals(NetworkStatsManager.CALLBACK_RELEASED, latchedHandler.mLastMessageType);
// Make sure that the caller binder gets disconnected // Make sure that the caller binder gets disconnected
EasyMock.verify(mockBinder); verify(mBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt());
} }
@Test
public void testUnregisterUsageCallback_unknown_noop() throws Exception { public void testUnregisterUsageCallback_unknown_noop() throws Exception {
String callingPackage = "the.calling.package"; String callingPackage = "the.calling.package";
long thresholdInBytes = 10 * 1024 * 1024; // 10 MB long thresholdInBytes = 10 * 1024 * 1024; // 10 MB
@@ -1061,33 +950,30 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
} }
private void expectSystemReady() throws Exception { private void expectSystemReady() throws Exception {
mNetManager.setGlobalAlert(anyLong());
expectLastCall().atLeastOnce();
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectBandwidthControlCheck(); expectBandwidthControlCheck();
} }
private void expectNetworkState(NetworkState... state) throws Exception { private void expectNetworkState(NetworkState... state) throws Exception {
expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce(); when(mConnManager.getAllNetworkState()).thenReturn(state);
final LinkProperties linkProp = state.length > 0 ? state[0].linkProperties : null; final LinkProperties linkProp = state.length > 0 ? state[0].linkProperties : null;
expect(mConnManager.getActiveLinkProperties()).andReturn(linkProp).atLeastOnce(); when(mConnManager.getActiveLinkProperties()).thenReturn(linkProp);
} }
private void expectNetworkStatsSummary(NetworkStats summary) throws Exception { private void expectNetworkStatsSummary(NetworkStats summary) throws Exception {
expect(mConnManager.getAllVpnInfo()).andReturn(new VpnInfo[0]).atLeastOnce(); when(mConnManager.getAllVpnInfo()).thenReturn(new VpnInfo[0]);
expectNetworkStatsSummaryDev(summary); expectNetworkStatsSummaryDev(summary);
expectNetworkStatsSummaryXt(summary); expectNetworkStatsSummaryXt(summary);
} }
private void expectNetworkStatsSummaryDev(NetworkStats summary) throws Exception { private void expectNetworkStatsSummaryDev(NetworkStats summary) throws Exception {
expect(mNetManager.getNetworkStatsSummaryDev()).andReturn(summary).atLeastOnce(); when(mNetManager.getNetworkStatsSummaryDev()).thenReturn(summary);
} }
private void expectNetworkStatsSummaryXt(NetworkStats summary) throws Exception { private void expectNetworkStatsSummaryXt(NetworkStats summary) throws Exception {
expect(mNetManager.getNetworkStatsSummaryXt()).andReturn(summary).atLeastOnce(); when(mNetManager.getNetworkStatsSummaryXt()).thenReturn(summary);
} }
private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception { private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception {
@@ -1097,11 +983,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
private void expectNetworkStatsUidDetail( private void expectNetworkStatsUidDetail(
NetworkStats detail, String[] tetherIfacePairs, NetworkStats tetherStats) NetworkStats detail, String[] tetherIfacePairs, NetworkStats tetherStats)
throws Exception { throws Exception {
expect(mNetManager.getNetworkStatsUidDetail(eq(UID_ALL))).andReturn(detail).atLeastOnce(); when(mNetManager.getNetworkStatsUidDetail(UID_ALL)).thenReturn(detail);
// also include tethering details, since they are folded into UID // also include tethering details, since they are folded into UID
expect(mNetManager.getNetworkStatsTethering()) when(mNetManager.getNetworkStatsTethering()).thenReturn(tetherStats);
.andReturn(tetherStats).atLeastOnce();
} }
private void expectDefaultSettings() throws Exception { private void expectDefaultSettings() throws Exception {
@@ -1110,38 +995,33 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
private void expectSettings(long persistBytes, long bucketDuration, long deleteAge) private void expectSettings(long persistBytes, long bucketDuration, long deleteAge)
throws Exception { throws Exception {
expect(mSettings.getPollInterval()).andReturn(HOUR_IN_MILLIS).anyTimes(); when(mSettings.getPollInterval()).thenReturn(HOUR_IN_MILLIS);
expect(mSettings.getTimeCacheMaxAge()).andReturn(DAY_IN_MILLIS).anyTimes(); when(mSettings.getTimeCacheMaxAge()).thenReturn(DAY_IN_MILLIS);
expect(mSettings.getSampleEnabled()).andReturn(true).anyTimes(); when(mSettings.getSampleEnabled()).thenReturn(true);
final Config config = new Config(bucketDuration, deleteAge, deleteAge); final Config config = new Config(bucketDuration, deleteAge, deleteAge);
expect(mSettings.getDevConfig()).andReturn(config).anyTimes(); when(mSettings.getDevConfig()).thenReturn(config);
expect(mSettings.getXtConfig()).andReturn(config).anyTimes(); when(mSettings.getXtConfig()).thenReturn(config);
expect(mSettings.getUidConfig()).andReturn(config).anyTimes(); when(mSettings.getUidConfig()).thenReturn(config);
expect(mSettings.getUidTagConfig()).andReturn(config).anyTimes(); when(mSettings.getUidTagConfig()).thenReturn(config);
expect(mSettings.getGlobalAlertBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); when(mSettings.getGlobalAlertBytes(anyLong())).thenReturn(MB_IN_BYTES);
expect(mSettings.getDevPersistBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); when(mSettings.getDevPersistBytes(anyLong())).thenReturn(MB_IN_BYTES);
expect(mSettings.getXtPersistBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); when(mSettings.getXtPersistBytes(anyLong())).thenReturn(MB_IN_BYTES);
expect(mSettings.getUidPersistBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); when(mSettings.getUidPersistBytes(anyLong())).thenReturn(MB_IN_BYTES);
expect(mSettings.getUidTagPersistBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); when(mSettings.getUidTagPersistBytes(anyLong())).thenReturn(MB_IN_BYTES);
} }
private void expectCurrentTime() throws Exception { private void expectCurrentTime() throws Exception {
expect(mTime.forceRefresh()).andReturn(false).anyTimes(); when(mTime.forceRefresh()).thenReturn(false);
expect(mTime.hasCache()).andReturn(true).anyTimes(); when(mTime.hasCache()).thenReturn(true);
expect(mTime.currentTimeMillis()).andReturn(currentTimeMillis()).anyTimes(); when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis());
expect(mTime.getCacheAge()).andReturn(0L).anyTimes(); when(mTime.getCacheAge()).thenReturn(0L);
expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes(); when(mTime.getCacheCertainty()).thenReturn(0L);
}
private void expectNetworkStatsPoll() throws Exception {
mNetManager.setGlobalAlert(anyLong());
expectLastCall().anyTimes();
} }
private void expectBandwidthControlCheck() throws Exception { private void expectBandwidthControlCheck() throws Exception {
expect(mNetManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce(); when(mNetManager.isBandwidthControlEnabled()).thenReturn(true);
} }
private void assertStatsFilesExist(boolean exist) { private void assertStatsFilesExist(boolean exist) {
@@ -1204,7 +1084,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
info.setDetailedState(DetailedState.CONNECTED, null, null); info.setDetailedState(DetailedState.CONNECTED, null, null);
final LinkProperties prop = new LinkProperties(); final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(TEST_IFACE); prop.setInterfaceName(TEST_IFACE);
return new NetworkState(info, prop, null, null, null, TEST_SSID); final NetworkCapabilities capabilities = new NetworkCapabilities();
return new NetworkState(info, prop, capabilities, null, null, TEST_SSID);
} }
private static NetworkState buildMobile3gState(String subscriberId) { private static NetworkState buildMobile3gState(String subscriberId) {
@@ -1218,7 +1099,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
info.setRoaming(isRoaming); info.setRoaming(isRoaming);
final LinkProperties prop = new LinkProperties(); final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(TEST_IFACE); prop.setInterfaceName(TEST_IFACE);
return new NetworkState(info, prop, null, null, subscriberId, null); final NetworkCapabilities capabilities = new NetworkCapabilities();
return new NetworkState(info, prop, capabilities, null, subscriberId, null);
} }
private static NetworkState buildMobile4gState(String iface) { private static NetworkState buildMobile4gState(String iface) {
@@ -1226,7 +1108,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
info.setDetailedState(DetailedState.CONNECTED, null, null); info.setDetailedState(DetailedState.CONNECTED, null, null);
final LinkProperties prop = new LinkProperties(); final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(iface); prop.setInterfaceName(iface);
return new NetworkState(info, prop, null, null, null, null); final NetworkCapabilities capabilities = new NetworkCapabilities();
return new NetworkState(info, prop, capabilities, null, null, null);
} }
private NetworkStats buildEmptyStats() { private NetworkStats buildEmptyStats() {
@@ -1249,15 +1132,6 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
mElapsedRealtime += duration; mElapsedRealtime += duration;
} }
private void replay() {
EasyMock.replay(mNetManager, mTime, mSettings, mConnManager);
}
private void verifyAndReset() {
EasyMock.verify(mNetManager, mTime, mSettings, mConnManager);
EasyMock.reset(mNetManager, mTime, mSettings, mConnManager);
}
private void forcePollAndWaitForIdle() { private void forcePollAndWaitForIdle() {
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// Send dummy message to make sure that any previous message has been handled // Send dummy message to make sure that any previous message has been handled

View File

@@ -68,14 +68,16 @@ import android.os.Process;
import android.os.SystemClock; import android.os.SystemClock;
import android.provider.Settings; import android.provider.Settings;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.test.FlakyTest;
import android.test.mock.MockContentResolver; import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log; import android.util.Log;
import android.util.LogPrinter; import android.util.LogPrinter;
import com.android.internal.util.FakeSettingsProvider;
import com.android.internal.util.WakeupMessage; 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.NetworkAgentInfo; import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor; import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult; import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
@@ -89,6 +91,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BooleanSupplier;
/** /**
* Tests for {@link ConnectivityService}. * Tests for {@link ConnectivityService}.
@@ -215,8 +218,20 @@ public class ConnectivityServiceTest extends AndroidTestCase {
mService.waitForIdle(); mService.waitForIdle();
assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength()); assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
} }
}
@FlakyTest(tolerance = 3)
public void testNotWaitingForIdleCausesRaceConditions() {
// Bring up a network that we can use to send messages to ConnectivityService.
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
waitFor(cv);
Network n = mWiFiNetworkAgent.getNetwork();
assertNotNull(n);
// Ensure that not calling waitForIdle causes a race condition. // Ensure that not calling waitForIdle causes a race condition.
final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
for (int i = 0; i < attempts; i++) { for (int i = 0; i < attempts; i++) {
mWiFiNetworkAgent.setSignalStrength(i); mWiFiNetworkAgent.setSignalStrength(i);
if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) { if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
@@ -608,7 +623,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
} }
private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker { private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker {
public boolean configRestrictsAvoidBadWifi; public volatile boolean configRestrictsAvoidBadWifi;
public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) { public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) {
super(c, h, r); super(c, h, r);
@@ -713,10 +728,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
static private void waitFor(Criteria criteria) { static private void waitFor(Criteria criteria) {
int delays = 0; int delays = 0;
while (!criteria.get()) { while (!criteria.get()) {
try { sleepFor(50);
Thread.sleep(50);
} catch (InterruptedException e) {
}
if (++delays == 10) fail(); if (++delays == 10) fail();
} }
} }
@@ -1086,7 +1098,8 @@ public class ConnectivityServiceTest extends AndroidTestCase {
NETWORK_CAPABILITIES, NETWORK_CAPABILITIES,
LINK_PROPERTIES, LINK_PROPERTIES,
LOSING, LOSING,
LOST LOST,
UNAVAILABLE
} }
private static class CallbackInfo { private static class CallbackInfo {
@@ -1134,6 +1147,11 @@ public class ConnectivityServiceTest extends AndroidTestCase {
setLastCallback(CallbackState.AVAILABLE, network, null); setLastCallback(CallbackState.AVAILABLE, network, null);
} }
@Override
public void onUnavailable() {
setLastCallback(CallbackState.UNAVAILABLE, null, null);
}
@Override @Override
public void onLosing(Network network, int maxMsToLive) { public void onLosing(Network network, int maxMsToLive) {
setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */); setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
@@ -1995,6 +2013,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
@SmallTest @SmallTest
public void testRequestBenchmark() throws Exception { public void testRequestBenchmark() throws Exception {
// TODO: turn this unit test into a real benchmarking test.
// Benchmarks connecting and switching performance in the presence of a large number of // Benchmarks connecting and switching performance in the presence of a large number of
// NetworkRequests. // NetworkRequests.
// 1. File NUM_REQUESTS requests. // 1. File NUM_REQUESTS requests.
@@ -2008,61 +2027,80 @@ public class ConnectivityServiceTest extends AndroidTestCase {
final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS); final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS); final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
final int REGISTER_TIME_LIMIT_MS = 100;
long startTime = System.currentTimeMillis();
for (int i = 0; i < NUM_REQUESTS; i++) { for (int i = 0; i < NUM_REQUESTS; i++) {
callbacks[i] = new NetworkCallback() { callbacks[i] = new NetworkCallback() {
@Override public void onAvailable(Network n) { availableLatch.countDown(); } @Override public void onAvailable(Network n) { availableLatch.countDown(); }
@Override public void onLosing(Network n, int t) { losingLatch.countDown(); } @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
}; };
mCm.registerNetworkCallback(request, callbacks[i]);
} }
long timeTaken = System.currentTimeMillis() - startTime;
String msg = String.format("Register %d callbacks: %dms, acceptable %dms",
NUM_REQUESTS, timeTaken, REGISTER_TIME_LIMIT_MS);
Log.d(TAG, msg);
assertTrue(msg, timeTaken < REGISTER_TIME_LIMIT_MS);
final int CONNECT_TIME_LIMIT_MS = 30; final int REGISTER_TIME_LIMIT_MS = 180;
assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
for (NetworkCallback cb : callbacks) {
mCm.registerNetworkCallback(request, cb);
}
});
final int CONNECT_TIME_LIMIT_MS = 40;
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
// Don't request that the network validate, because otherwise connect() will block until // Don't request that the network validate, because otherwise connect() will block until
// the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired, // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
// and we won't actually measure anything. // and we won't actually measure anything.
mCellNetworkAgent.connect(false); mCellNetworkAgent.connect(false);
startTime = System.currentTimeMillis();
if (!availableLatch.await(CONNECT_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) {
fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
CONNECT_TIME_LIMIT_MS));
}
timeTaken = System.currentTimeMillis() - startTime;
Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
NUM_REQUESTS, timeTaken, CONNECT_TIME_LIMIT_MS));
final int SWITCH_TIME_LIMIT_MS = 30; long onAvailableDispatchingDuration = durationOf(() -> {
if (!awaitLatch(availableLatch, CONNECT_TIME_LIMIT_MS)) {
fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
CONNECT_TIME_LIMIT_MS));
}
});
Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS));
final int SWITCH_TIME_LIMIT_MS = 40;
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
// Give wifi a high enough score that we'll linger cell when wifi comes up. // Give wifi a high enough score that we'll linger cell when wifi comes up.
mWiFiNetworkAgent.adjustScore(40); mWiFiNetworkAgent.adjustScore(40);
mWiFiNetworkAgent.connect(false); mWiFiNetworkAgent.connect(false);
startTime = System.currentTimeMillis();
if (!losingLatch.await(SWITCH_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) { long onLostDispatchingDuration = durationOf(() -> {
fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms", if (!awaitLatch(losingLatch, SWITCH_TIME_LIMIT_MS)) {
NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS)); fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
} NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
timeTaken = System.currentTimeMillis() - startTime; }
});
Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms", Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
NUM_REQUESTS, timeTaken, SWITCH_TIME_LIMIT_MS)); NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS));
final int UNREGISTER_TIME_LIMIT_MS = 10; final int UNREGISTER_TIME_LIMIT_MS = 10;
startTime = System.currentTimeMillis(); assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
for (int i = 0; i < NUM_REQUESTS; i++) { for (NetworkCallback cb : callbacks) {
mCm.unregisterNetworkCallback(callbacks[i]); mCm.unregisterNetworkCallback(cb);
} }
timeTaken = System.currentTimeMillis() - startTime; });
msg = String.format("Unregister %d callbacks: %dms, acceptable %dms", }
NUM_REQUESTS, timeTaken, UNREGISTER_TIME_LIMIT_MS);
private long durationOf(Runnable fn) {
long startTime = SystemClock.elapsedRealtime();
fn.run();
return SystemClock.elapsedRealtime() - startTime;
}
private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
long timeTaken = durationOf(fn);
String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Log.d(TAG, msg); Log.d(TAG, msg);
assertTrue(msg, timeTaken < UNREGISTER_TIME_LIMIT_MS); assertTrue(msg, timeTaken <= timeLimit);
}
private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
try {
if (l.await(timeoutMs, TimeUnit.MILLISECONDS)) {
return true;
}
} catch (InterruptedException e) {}
return false;
} }
@SmallTest @SmallTest
@@ -2143,7 +2181,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
tracker.reevaluate(); tracker.reevaluate();
mService.waitForIdle(); mService.waitForIdle();
String msg = String.format("config=false, setting=%s", values[i]); String msg = String.format("config=false, setting=%s", values[i]);
assertTrue(msg, mService.avoidBadWifi()); assertEventuallyTrue(() -> mService.avoidBadWifi(), 50);
assertFalse(msg, tracker.shouldNotifyWifiUnvalidated()); assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
} }
@@ -2152,19 +2190,19 @@ public class ConnectivityServiceTest extends AndroidTestCase {
Settings.Global.putInt(cr, settingName, 0); Settings.Global.putInt(cr, settingName, 0);
tracker.reevaluate(); tracker.reevaluate();
mService.waitForIdle(); mService.waitForIdle();
assertFalse(mService.avoidBadWifi()); assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50);
assertFalse(tracker.shouldNotifyWifiUnvalidated()); assertFalse(tracker.shouldNotifyWifiUnvalidated());
Settings.Global.putInt(cr, settingName, 1); Settings.Global.putInt(cr, settingName, 1);
tracker.reevaluate(); tracker.reevaluate();
mService.waitForIdle(); mService.waitForIdle();
assertTrue(mService.avoidBadWifi()); assertEventuallyTrue(() -> mService.avoidBadWifi(), 50);
assertFalse(tracker.shouldNotifyWifiUnvalidated()); assertFalse(tracker.shouldNotifyWifiUnvalidated());
Settings.Global.putString(cr, settingName, null); Settings.Global.putString(cr, settingName, null);
tracker.reevaluate(); tracker.reevaluate();
mService.waitForIdle(); mService.waitForIdle();
assertFalse(mService.avoidBadWifi()); assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50);
assertTrue(tracker.shouldNotifyWifiUnvalidated()); assertTrue(tracker.shouldNotifyWifiUnvalidated());
} }
@@ -2291,6 +2329,107 @@ public class ConnectivityServiceTest extends AndroidTestCase {
mCm.unregisterNetworkCallback(defaultCallback); mCm.unregisterNetworkCallback(defaultCallback);
} }
/**
* Validate that a satisfied network request does not trigger onUnavailable() once the
* time-out period expires.
*/
@SmallTest
public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
mCm.requestNetwork(nr, networkCallback, 10);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
// pass timeout and validate that UNAVAILABLE is not called
sleepFor(15);
networkCallback.assertNoCallback();
}
/**
* Validate that a satisfied network request followed by a disconnected (lost) network does
* not trigger onUnavailable() once the time-out period expires.
*/
@SmallTest
public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
mCm.requestNetwork(nr, networkCallback, 500);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
sleepFor(20);
mWiFiNetworkAgent.disconnect();
networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
// pass timeout and validate that UNAVAILABLE is not called
sleepFor(600);
networkCallback.assertNoCallback();
}
/**
* Validate that when a time-out is specified for a network request the onUnavailable()
* callback is called when time-out expires. Then validate that if network request is
* (somehow) satisfied - the callback isn't called later.
*/
@SmallTest
public void testTimedoutNetworkRequest() {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
mCm.requestNetwork(nr, networkCallback, 10);
// pass timeout and validate that UNAVAILABLE is called
networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
// create a network satisfying request - validate that request not triggered
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
networkCallback.assertNoCallback();
}
/**
* Validate that when a network request is unregistered (cancelled) the time-out for that
* request doesn't trigger the onUnavailable() callback.
*/
@SmallTest
public void testTimedoutAfterUnregisteredNetworkRequest() {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
mCm.requestNetwork(nr, networkCallback, 10);
// remove request
mCm.unregisterNetworkCallback(networkCallback);
// pass timeout and validate that no callbacks
// Note: doesn't validate that nothing called from CS since even if called the CM already
// unregisters the callback and won't pass it through!
sleepFor(15);
networkCallback.assertNoCallback();
// create a network satisfying request - validate that request not triggered
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
networkCallback.assertNoCallback();
}
public void assertEventuallyTrue(BooleanSupplier fn, long maxWaitingTimeMs) throws Exception {
long start = SystemClock.elapsedRealtime();
while (SystemClock.elapsedRealtime() <= start + maxWaitingTimeMs) {
if (fn.getAsBoolean()) {
return;
}
Thread.sleep(10);
}
assertTrue(fn.getAsBoolean());
}
private static class TestKeepaliveCallback extends PacketKeepaliveCallback { private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }; public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
@@ -2695,4 +2834,13 @@ public class ConnectivityServiceTest extends AndroidTestCase {
mCm.unregisterNetworkCallback(pendingIntent); mCm.unregisterNetworkCallback(pendingIntent);
} }
} }
/* test utilities */
static private void sleepFor(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
}
}
} }

View File

@@ -71,7 +71,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" transport_types: 3", " transport_types: 3",
" >", " >",
" time_ms: 1", " time_ms: 1",
">"); ">",
"version: 2");
verifySerialization(want, ev); verifySerialization(want, ev);
} }
@@ -93,7 +94,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" state_transition: \"SomeState\"", " state_transition: \"SomeState\"",
" >", " >",
" time_ms: 1", " time_ms: 1",
">"); ">",
"version: 2");
verifySerialization(want, ev); verifySerialization(want, ev);
} }
@@ -114,7 +116,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" state_transition: \"\"", " state_transition: \"\"",
" >", " >",
" time_ms: 1", " time_ms: 1",
">"); ">",
"version: 2");
verifySerialization(want, ev); verifySerialization(want, ev);
} }
@@ -160,7 +163,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" return_codes: 178", " return_codes: 178",
" >", " >",
" time_ms: 1", " time_ms: 1",
">"); ">",
"version: 2");
verifySerialization(want, ev); verifySerialization(want, ev);
} }
@@ -181,7 +185,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" latency_ms: 5678", " latency_ms: 5678",
" >", " >",
" time_ms: 1", " time_ms: 1",
">"); ">",
"version: 2");
verifySerialization(want, ev); verifySerialization(want, ev);
} }
@@ -200,7 +205,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" if_name: \"wlan0\"", " if_name: \"wlan0\"",
" >", " >",
" time_ms: 1", " time_ms: 1",
">"); ">",
"version: 2");
verifySerialization(want, ev); verifySerialization(want, ev);
} }
@@ -223,7 +229,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" >", " >",
" >", " >",
" time_ms: 1", " time_ms: 1",
">"); ">",
"version: 2");
verifySerialization(want, ev); verifySerialization(want, ev);
} }
@@ -248,7 +255,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" probe_result: 204", " probe_result: 204",
" probe_type: 1", " probe_type: 1",
" >", " >",
">"); ">",
"version: 2");
verifySerialization(want, ev); verifySerialization(want, ev);
} }
@@ -274,7 +282,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" program_length: 2048", " program_length: 2048",
" >", " >",
" time_ms: 1", " time_ms: 1",
">"); ">",
"version: 2");
verifySerialization(want, ev); verifySerialization(want, ev);
} }
@@ -305,7 +314,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" zero_lifetime_ras: 1", " zero_lifetime_ras: 1",
" >", " >",
" time_ms: 1", " time_ms: 1",
">"); ">",
"version: 2");
verifySerialization(want, ev); verifySerialization(want, ev);
} }
@@ -332,7 +342,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" router_lifetime: 2000", " router_lifetime: 2000",
" >", " >",
" time_ms: 1", " time_ms: 1",
">"); ">",
"version: 2");
verifySerialization(want, ev); verifySerialization(want, ev);
} }

View File

@@ -57,7 +57,7 @@ public class IpConnectivityMetricsTest extends TestCase {
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mService = new IpConnectivityMetrics(mCtx); mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000);
} }
public void testLoggingEvents() throws Exception { public void testLoggingEvents() throws Exception {
@@ -204,7 +204,8 @@ public class IpConnectivityMetricsTest extends TestCase {
" router_lifetime: 2000", " router_lifetime: 2000",
" >", " >",
" time_ms: 700", " time_ms: 700",
">"); ">",
"version: 2");
verifySerialization(want, getdump("flush")); verifySerialization(want, getdump("flush"));
} }