From 094fbe671927b730a30f4914ddc08f997ffc0114 Mon Sep 17 00:00:00 2001 From: Tony Mak Date: Thu, 30 Jun 2016 11:19:20 +0100 Subject: [PATCH 1/9] Show notification for always-on app VPN This is the same notification as the one shown during legacy lockdown mode, sans the 'reset' button. The notification is only shown during times when VPN has not yet established or has failed, for example during boot or after a crash. Bug: 29123115 (cherry picked from commit 1a405fe300950d6ceae2166fd074b596d8110dbe) Change-Id: I929a05c24df01e21415535a333bb14ac4b790a9d --- .../com/android/server/connectivity/Vpn.java | 64 ++++++++++--- .../android/server/connectivity/VpnTest.java | 91 +++++++++++++------ 2 files changed, 117 insertions(+), 38 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 610a2ab5b53bd..a5876ddda745c 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -27,6 +27,8 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.AppGlobals; import android.app.AppOpsManager; +import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -76,6 +78,7 @@ import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; +import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.net.LegacyVpnInfo; @@ -241,12 +244,14 @@ public class Vpn { /** * Update current state, dispaching event to listeners. */ - private void updateState(DetailedState detailedState, String reason) { + @VisibleForTesting + protected void updateState(DetailedState detailedState, String reason) { if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason); mNetworkInfo.setDetailedState(detailedState, reason, null); if (mNetworkAgent != null) { mNetworkAgent.sendNetworkInfo(mNetworkInfo); } + updateAlwaysOnNotification(detailedState); } /** @@ -280,7 +285,10 @@ public class Vpn { } mLockdown = (mAlwaysOn && lockdown); - if (!isCurrentPreparedPackage(packageName)) { + if (isCurrentPreparedPackage(packageName)) { + updateAlwaysOnNotification(mNetworkInfo.getDetailedState()); + } else { + // Prepare this app. The notification will update as a side-effect of updateState(). prepareInternal(packageName); } maybeRegisterPackageChangeReceiverLocked(packageName); @@ -682,22 +690,19 @@ public class Vpn { } } - private void agentDisconnect(NetworkInfo networkInfo, NetworkAgent networkAgent) { - networkInfo.setIsAvailable(false); - networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); + private void agentDisconnect(NetworkAgent networkAgent) { if (networkAgent != null) { + NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo); + networkInfo.setIsAvailable(false); + networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); networkAgent.sendNetworkInfo(networkInfo); } } - private void agentDisconnect(NetworkAgent networkAgent) { - NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo); - agentDisconnect(networkInfo, networkAgent); - } - private void agentDisconnect() { if (mNetworkInfo.isConnected()) { - agentDisconnect(mNetworkInfo, mNetworkAgent); + mNetworkInfo.setIsAvailable(false); + updateState(DetailedState.DISCONNECTED, "agentDisconnect"); mNetworkAgent = null; } } @@ -1250,6 +1255,43 @@ public class Vpn { } } + private void updateAlwaysOnNotification(DetailedState networkState) { + final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED); + updateAlwaysOnNotificationInternal(visible); + } + + @VisibleForTesting + protected void updateAlwaysOnNotificationInternal(boolean visible) { + final UserHandle user = UserHandle.of(mUserHandle); + final long token = Binder.clearCallingIdentity(); + try { + final NotificationManager notificationManager = NotificationManager.from(mContext); + if (!visible) { + notificationManager.cancelAsUser(TAG, 0, user); + return; + } + final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS); + final PendingIntent configIntent = PendingIntent.getActivityAsUser( + mContext, /* request */ 0, intent, + PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, + null, user); + final Notification.Builder builder = new Notification.Builder(mContext) + .setDefaults(0) + .setSmallIcon(R.drawable.vpn_connected) + .setContentTitle(mContext.getString(R.string.vpn_lockdown_disconnected)) + .setContentText(mContext.getString(R.string.vpn_lockdown_config)) + .setContentIntent(configIntent) + .setCategory(Notification.CATEGORY_SYSTEM) + .setPriority(Notification.PRIORITY_LOW) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setOngoing(true) + .setColor(mContext.getColor(R.color.system_notification_accent_color)); + notificationManager.notifyAsUser(TAG, 0, builder.build(), user); + } finally { + Binder.restoreCallingIdentity(token); + } + } + private native int jniCreate(int mtu); private native String jniGetName(int tun); private native int jniSetAddresses(String interfaze, String addresses); diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 5d8b843bbc172..b51b2771db168 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -25,9 +25,11 @@ import static org.mockito.Mockito.*; import android.annotation.UserIdInt; import android.app.AppOpsManager; +import android.app.NotificationManager; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.UserInfo; +import android.net.NetworkInfo.DetailedState; import android.net.UidRange; import android.os.INetworkManagementService; import android.os.Looper; @@ -43,6 +45,8 @@ import java.util.Arrays; import java.util.Map; import java.util.Set; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -88,14 +92,18 @@ public class VpnTest extends AndroidTestCase { @Mock private PackageManager mPackageManager; @Mock private INetworkManagementService mNetService; @Mock private AppOpsManager mAppOps; + @Mock private NotificationManager mNotificationManager; @Override public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mContext.getPackageManager()).thenReturn(mPackageManager); setMockedPackages(mPackages); + when(mContext.getPackageName()).thenReturn(Vpn.class.getPackage().getName()); when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps); + when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE))) + .thenReturn(mNotificationManager); doNothing().when(mNetService).registerObserver(any()); } @@ -103,7 +111,7 @@ public class VpnTest extends AndroidTestCase { public void testRestrictedProfilesAreAddedToVpn() { setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB); - final Vpn vpn = new MockVpn(primaryUser.id); + final Vpn vpn = spyVpn(primaryUser.id); final Set ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); @@ -117,7 +125,7 @@ public class VpnTest extends AndroidTestCase { public void testManagedProfilesAreNotAddedToVpn() { setMockedUsers(primaryUser, managedProfileA); - final Vpn vpn = new MockVpn(primaryUser.id); + final Vpn vpn = spyVpn(primaryUser.id); final Set ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); @@ -130,7 +138,7 @@ public class VpnTest extends AndroidTestCase { public void testAddUserToVpnOnlyAddsOneUser() { setMockedUsers(primaryUser, restrictedProfileA, managedProfileA); - final Vpn vpn = new MockVpn(primaryUser.id); + final Vpn vpn = spyVpn(primaryUser.id); final Set ranges = new ArraySet<>(); vpn.addUserToRanges(ranges, primaryUser.id, null, null); @@ -141,7 +149,7 @@ public class VpnTest extends AndroidTestCase { @SmallTest public void testUidWhiteAndBlacklist() throws Exception { - final Vpn vpn = new MockVpn(primaryUser.id); + final Vpn vpn = spyVpn(primaryUser.id); final UidRange user = UidRange.createForUser(primaryUser.id); final String[] packages = {PKGS[0], PKGS[1], PKGS[2]}; @@ -166,15 +174,15 @@ public class VpnTest extends AndroidTestCase { @SmallTest public void testLockdownChangingPackage() throws Exception { - final MockVpn vpn = new MockVpn(primaryUser.id); + final Vpn vpn = spyVpn(primaryUser.id); final UidRange user = UidRange.createForUser(primaryUser.id); // Default state. - vpn.assertUnblocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); + assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on without lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false)); - vpn.assertUnblocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); + assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on with lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true)); @@ -182,8 +190,8 @@ public class VpnTest extends AndroidTestCase { new UidRange(user.start, user.start + PKG_UIDS[1] - 1), new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) })); - vpn.assertBlocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); - vpn.assertUnblocked(user.start + PKG_UIDS[1]); + assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); + assertUnblocked(vpn, user.start + PKG_UIDS[1]); // Switch to another app. assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true)); @@ -195,13 +203,13 @@ public class VpnTest extends AndroidTestCase { new UidRange(user.start, user.start + PKG_UIDS[3] - 1), new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) })); - vpn.assertBlocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); - vpn.assertUnblocked(user.start + PKG_UIDS[3]); + assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); + assertUnblocked(vpn, user.start + PKG_UIDS[3]); } @SmallTest public void testLockdownAddingAProfile() throws Exception { - final MockVpn vpn = new MockVpn(primaryUser.id); + final Vpn vpn = spyVpn(primaryUser.id); setMockedUsers(primaryUser); // Make a copy of the restricted profile, as we're going to mark it deleted halfway through. @@ -220,7 +228,7 @@ public class VpnTest extends AndroidTestCase { })); // Verify restricted user isn't affected at first. - vpn.assertUnblocked(profile.start + PKG_UIDS[0]); + assertUnblocked(vpn, profile.start + PKG_UIDS[0]); // Add the restricted user. setMockedUsers(primaryUser, tempProfile); @@ -239,24 +247,53 @@ public class VpnTest extends AndroidTestCase { })); } + @SmallTest + public void testNotificationShownForAlwaysOnApp() { + final Vpn vpn = spyVpn(primaryUser.id); + final InOrder order = inOrder(vpn); + setMockedUsers(primaryUser); + + // Don't show a notification for regular disconnected states. + vpn.updateState(DetailedState.DISCONNECTED, TAG); + order.verify(vpn).updateAlwaysOnNotificationInternal(false); + + // Start showing a notification for disconnected once always-on. + vpn.setAlwaysOnPackage(PKGS[0], false); + order.verify(vpn).updateAlwaysOnNotificationInternal(true); + + // Stop showing the notification once connected. + vpn.updateState(DetailedState.CONNECTED, TAG); + order.verify(vpn).updateAlwaysOnNotificationInternal(false); + + // Show the notification if we disconnect again. + vpn.updateState(DetailedState.DISCONNECTED, TAG); + order.verify(vpn).updateAlwaysOnNotificationInternal(true); + + // Notification should be cleared after unsetting always-on package. + vpn.setAlwaysOnPackage(null, false); + order.verify(vpn).updateAlwaysOnNotificationInternal(false); + } + /** - * A subclass of {@link Vpn} with some of the fields pre-mocked. + * Mock some methods of vpn object. */ - private class MockVpn extends Vpn { - public MockVpn(@UserIdInt int userId) { - super(Looper.myLooper(), mContext, mNetService, userId); - } + private Vpn spyVpn(@UserIdInt int userId) { + final Vpn vpn = spy(new Vpn(Looper.myLooper(), mContext, mNetService, userId)); - public void assertBlocked(int... uids) { - for (int uid : uids) { - assertTrue("Uid " + uid + " should be blocked", isBlockingUid(uid)); - } - } + // Block calls to the NotificationManager or PendingIntent#getActivity. + doNothing().when(vpn).updateAlwaysOnNotificationInternal(anyBoolean()); + return vpn; + } - public void assertUnblocked(int... uids) { - for (int uid : uids) { - assertFalse("Uid " + uid + " should not be blocked", isBlockingUid(uid)); - } + private static void assertBlocked(Vpn vpn, int... uids) { + for (int uid : uids) { + assertTrue("Uid " + uid + " should be blocked", vpn.isBlockingUid(uid)); + } + } + + private static void assertUnblocked(Vpn vpn, int... uids) { + for (int uid : uids) { + assertFalse("Uid " + uid + " should not be blocked", vpn.isBlockingUid(uid)); } } From bea525eff8b74540cce95cf9507cff4f08c57824 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 9 Dec 2016 14:19:57 +0900 Subject: [PATCH 2/9] Add missing dependency. Change-Id: I5deb8e03eb368ab7003f9376f7b4459d2ef5e934 --- services/tests/servicestests/Android.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk index d3235d8fb086c..336351ebbef56 100644 --- a/services/tests/servicestests/Android.mk +++ b/services/tests/servicestests/Android.mk @@ -12,6 +12,7 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_STATIC_JAVA_LIBRARIES := \ + easymocklib \ frameworks-base-testutils \ services.core \ services.devicepolicy \ From 222ebe48ba33165caead08f19831cb593d5d4db7 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Mon, 31 Oct 2016 15:04:37 +0900 Subject: [PATCH 3/9] Netd events: record connect() success/errno Test: $ runtest frameworks-net pass Bug: 32198976 (cherry picked from commit 8b06bcdfd24100302818ae0e11ee751dd813d5cf) Change-Id: Ib3be06d2678c3fcfe4fa9d7b77f50c6e8812db3d --- .../NetdEventListenerService.java | 25 ++++++++++--------- .../NetdEventListenerServiceTest.java | 11 +++++--- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java index 4b175d7a5af80..f8638c544e8ef 100644 --- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java +++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java @@ -24,6 +24,7 @@ import android.net.NetworkRequest; import android.net.metrics.DnsEvent; import android.net.metrics.INetdEventListener; import android.net.metrics.IpConnectivityLog; +import android.os.RemoteException; import android.util.Log; import com.android.internal.annotations.GuardedBy; @@ -44,7 +45,7 @@ public class NetdEventListenerService extends INetdEventListener.Stub { public static final String SERVICE_NAME = "netd_listener"; private static final String TAG = NetdEventListenerService.class.getSimpleName(); - private static final boolean DBG = true; + private static final boolean DBG = false; private static final boolean VDBG = false; // TODO: read this constant from system property @@ -86,7 +87,7 @@ public class NetdEventListenerService extends INetdEventListener.Stub { byte[] returnCodes = Arrays.copyOf(mReturnCodes, mEventCount); int[] latenciesMs = Arrays.copyOf(mLatenciesMs, mEventCount); mMetricsLog.log(new DnsEvent(mNetId, eventTypes, returnCodes, latenciesMs)); - maybeLog(String.format("Logging %d results for netId %d", mEventCount, mNetId)); + maybeLog("Logging %d results for netId %d", mEventCount, mNetId); mEventCount = 0; } @@ -136,9 +137,9 @@ public class NetdEventListenerService extends INetdEventListener.Stub { // Called concurrently by multiple binder threads. // This method must not block or perform long-running operations. public synchronized void onDnsEvent(int netId, int eventType, int returnCode, int latencyMs, - String hostname, String[] ipAddresses, int ipAddressesCount, int uid) { - maybeVerboseLog(String.format("onDnsEvent(%d, %d, %d, %d)", - netId, eventType, returnCode, latencyMs)); + String hostname, String[] ipAddresses, int ipAddressesCount, int uid) + throws RemoteException { + maybeVerboseLog("onDnsEvent(%d, %d, %d, %dms)", netId, eventType, returnCode, latencyMs); DnsEventBatch batch = mEventBatches.get(netId); if (batch == null) { @@ -151,9 +152,9 @@ public class NetdEventListenerService extends INetdEventListener.Stub { @Override // Called concurrently by multiple binder threads. // This method must not block or perform long-running operations. - public synchronized void onConnectEvent(int netId, int latencyMs, String ipAddr, int port, - int uid) { - maybeVerboseLog(String.format("onConnectEvent(%d, %d)", netId, latencyMs)); + public synchronized void onConnectEvent(int netId, int error, int latencyMs, String ipAddr, int port, + int uid) throws RemoteException { + maybeVerboseLog("onConnectEvent(%d, %d, %dms)", netId, error, latencyMs); } public synchronized void dump(PrintWriter writer) { @@ -166,11 +167,11 @@ public class NetdEventListenerService extends INetdEventListener.Stub { pw.decreaseIndent(); } - private static void maybeLog(String s) { - if (DBG) Log.d(TAG, s); + private static void maybeLog(String s, Object... args) { + if (DBG) Log.d(TAG, String.format(s, args)); } - private static void maybeVerboseLog(String s) { - if (VDBG) Log.d(TAG, s); + private static void maybeVerboseLog(String s, Object... args) { + if (VDBG) Log.d(TAG, String.format(s, args)); } } diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java index 9e2fd6231ba9d..af4a374bffddf 100644 --- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java +++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java @@ -22,6 +22,7 @@ import android.net.Network; import android.net.metrics.DnsEvent; import android.net.metrics.INetdEventListener; import android.net.metrics.IpConnectivityLog; +import android.os.RemoteException; import junit.framework.TestCase; import org.junit.Before; @@ -157,9 +158,13 @@ public class NetdEventListenerServiceTest extends TestCase { } void log(int netId, int[] latencies) { - for (int l : latencies) { - mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l, null, null, 0, - 0); + try { + for (int l : latencies) { + mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l, null, null, + 0, 0); + } + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); } } From 352147a308e4cdc4ccf82af83d37d1505fe1b05d Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Fri, 4 Nov 2016 16:06:34 +0900 Subject: [PATCH 4/9] frameworks-test: adding missing @SmallTest This activates all frameworks-test tests in runs of the continuous platform tests. Test: $ runtest frameworks-net passes (expect Tether Bug: 32561414 (cherry picked from commit fa8a6f6220d1a0027ba7969c2d3f72690ddc6495) Change-Id: I7b0706a7e3368f971d508388e8ad4afc5de9d646 --- .../net/ConnectivityMetricsLoggerTest.java | 6 +++ tests/net/java/android/net/apf/ApfTest.java | 15 ++++---- .../java/android/net/dhcp/DhcpPacketTest.java | 2 + .../net/netlink/NetlinkErrorMessageTest.java | 2 + .../net/netlink/NetlinkSocketTest.java | 3 ++ .../netlink/RtNetlinkNeighborMessageTest.java | 7 +++- .../server/ConnectivityServiceTest.java | 38 ++++++++++--------- .../connectivity/LingerMonitorTest.java | 16 ++++++++ .../MetricsLoggerServiceTest.java | 7 ++++ .../NetdEventListenerServiceTest.java | 6 +++ 10 files changed, 75 insertions(+), 27 deletions(-) diff --git a/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java b/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java index 6d42cce2e5027..f89603052213b 100644 --- a/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java +++ b/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java @@ -18,6 +18,7 @@ package android.net; import android.os.Bundle; import android.os.Parcel; +import android.test.suitebuilder.annotation.SmallTest; import java.util.List; import junit.framework.TestCase; import org.mockito.ArgumentCaptor; @@ -49,6 +50,7 @@ public class ConnectivityMetricsLoggerTest extends TestCase { mLog = new ConnectivityMetricsLogger(mService); } + @SmallTest public void testLogEvents() throws Exception { mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); @@ -60,6 +62,7 @@ public class ConnectivityMetricsLoggerTest extends TestCase { assertEventsEqual(expectedEvent(3), gotEvents.get(2)); } + @SmallTest public void testLogEventTriggerThrottling() throws Exception { when(mService.logEvent(any())).thenReturn(1234L); @@ -70,6 +73,7 @@ public class ConnectivityMetricsLoggerTest extends TestCase { assertEventsEqual(expectedEvent(1), gotEvents.get(0)); } + @SmallTest public void testLogEventFails() throws Exception { when(mService.logEvent(any())).thenReturn(-1L); // Error. @@ -80,6 +84,7 @@ public class ConnectivityMetricsLoggerTest extends TestCase { assertEventsEqual(expectedEvent(1), gotEvents.get(0)); } + @SmallTest public void testLogEventWhenThrottling() throws Exception { when(mService.logEvent(any())).thenReturn(Long.MAX_VALUE); // Throttled @@ -92,6 +97,7 @@ public class ConnectivityMetricsLoggerTest extends TestCase { assertEventsEqual(expectedEvent(1), gotEvents.get(0)); } + @SmallTest public void testLogEventRecoverFromThrottling() throws Exception { final long throttleTimeout = System.currentTimeMillis() + 10; when(mService.logEvent(any())).thenReturn(throttleTimeout, 0L); diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java index f41ea922305b4..ff6175427ce71 100644 --- a/tests/net/java/android/net/apf/ApfTest.java +++ b/tests/net/java/android/net/apf/ApfTest.java @@ -33,7 +33,6 @@ import android.system.ErrnoException; import android.system.Os; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; -import android.test.suitebuilder.annotation.MediumTest; import static android.system.OsConstants.*; import com.android.frameworks.tests.net.R; @@ -155,7 +154,7 @@ public class ApfTest extends AndroidTestCase { * generating bytecode for that program and running it through the * interpreter to verify it functions correctly. */ - @MediumTest + @SmallTest public void testApfInstructions() throws IllegalInstructionException { // Empty program should pass because having the program counter reach the // location immediately after the program indicates the packet should be @@ -563,7 +562,7 @@ public class ApfTest extends AndroidTestCase { * Generate some BPF programs, translate them to APF, then run APF and BPF programs * over packet traces and verify both programs filter out the same packets. */ - @MediumTest + @SmallTest public void testApfAgainstBpf() throws Exception { String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53", "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24", @@ -725,7 +724,7 @@ public class ApfTest extends AndroidTestCase { private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2}; private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0}; - @MediumTest + @SmallTest public void testApfFilterIPv4() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); @@ -780,7 +779,7 @@ public class ApfTest extends AndroidTestCase { apfFilter.shutdown(); } - @MediumTest + @SmallTest public void testApfFilterIPv6() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog); @@ -812,7 +811,7 @@ public class ApfTest extends AndroidTestCase { apfFilter.shutdown(); } - @MediumTest + @SmallTest public void testApfFilterMulticast() throws Exception { final byte[] unicastIpv4Addr = {(byte)192,0,2,63}; final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255}; @@ -922,7 +921,7 @@ public class ApfTest extends AndroidTestCase { assertDrop(program, garpReply()); } - @MediumTest + @SmallTest public void testApfFilterArp() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog); @@ -1041,7 +1040,7 @@ public class ApfTest extends AndroidTestCase { ipManagerCallback.assertNoProgramUpdate(); } - @MediumTest + @SmallTest public void testApfFilterRa() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog); diff --git a/tests/net/java/android/net/dhcp/DhcpPacketTest.java b/tests/net/java/android/net/dhcp/DhcpPacketTest.java index bc8baa12a45b4..d79c312a9edd5 100644 --- a/tests/net/java/android/net/dhcp/DhcpPacketTest.java +++ b/tests/net/java/android/net/dhcp/DhcpPacketTest.java @@ -473,6 +473,7 @@ public class DhcpPacketTest extends TestCase { assertEquals(Integer.toHexString(expected), Integer.toHexString(got)); } + @SmallTest public void testTruncatedOfferPackets() throws Exception { final byte[] packet = HexDump.hexStringToByteArray( // IP header. @@ -506,6 +507,7 @@ public class DhcpPacketTest extends TestCase { } } + @SmallTest public void testRandomPackets() throws Exception { final int maxRandomPacketSize = 512; final Random r = new Random(); diff --git a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java index e677475f5907b..5deba27d80dcd 100644 --- a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java +++ b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java @@ -24,6 +24,7 @@ import android.net.netlink.NetlinkConstants; import android.net.netlink.NetlinkErrorMessage; import android.net.netlink.NetlinkMessage; import android.net.netlink.StructNlMsgErr; +import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -53,6 +54,7 @@ public class NetlinkErrorMessageTest extends TestCase { public static final byte[] NLM_ERROR_OK = HexEncoding.decode(NLM_ERROR_OK_HEX.toCharArray(), false); + @SmallTest public void testParseNlmErrorOk() { final ByteBuffer byteBuffer = ByteBuffer.wrap(NLM_ERROR_OK); byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. diff --git a/tests/net/java/android/net/netlink/NetlinkSocketTest.java b/tests/net/java/android/net/netlink/NetlinkSocketTest.java index c599fe3e5b762..78b3b704e7868 100644 --- a/tests/net/java/android/net/netlink/NetlinkSocketTest.java +++ b/tests/net/java/android/net/netlink/NetlinkSocketTest.java @@ -20,6 +20,7 @@ import android.net.netlink.NetlinkSocket; import android.net.netlink.RtNetlinkNeighborMessage; import android.net.netlink.StructNdMsg; import android.net.netlink.StructNlMsgHdr; +import android.test.suitebuilder.annotation.SmallTest; import android.system.ErrnoException; import android.system.NetlinkSocketAddress; import android.system.OsConstants; @@ -33,6 +34,7 @@ import junit.framework.TestCase; public class NetlinkSocketTest extends TestCase { private final String TAG = "NetlinkSocketTest"; + @SmallTest public void testBasicWorkingGetNeighborsQuery() throws Exception { NetlinkSocket s = new NetlinkSocket(OsConstants.NETLINK_ROUTE); assertNotNull(s); @@ -91,6 +93,7 @@ public class NetlinkSocketTest extends TestCase { s.close(); } + @SmallTest public void testRepeatedCloseCallsAreQuiet() throws Exception { // Create a working NetlinkSocket. NetlinkSocket s = new NetlinkSocket(OsConstants.NETLINK_ROUTE); diff --git a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java index 19ee00036b612..029758eb6e5b6 100644 --- a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java +++ b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java @@ -21,12 +21,13 @@ import android.net.netlink.NetlinkMessage; import android.net.netlink.RtNetlinkNeighborMessage; import android.net.netlink.StructNdMsg; import android.net.netlink.StructNlMsgHdr; +import android.test.suitebuilder.annotation.SmallTest; import android.system.OsConstants; import android.util.Log; import libcore.util.HexEncoding; -import java.net.InetAddress; import java.net.Inet4Address; +import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -135,6 +136,7 @@ public class RtNetlinkNeighborMessageTest extends TestCase { public static final byte[] RTM_GETNEIGH_RESPONSE = HexEncoding.decode(RTM_GETNEIGH_RESPONSE_HEX.replaceAll(" ", "").toCharArray(), false); + @SmallTest public void testParseRtmDelNeigh() { final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_DELNEIGH); byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. @@ -161,6 +163,7 @@ public class RtNetlinkNeighborMessageTest extends TestCase { assertEquals(InetAddress.parseNumericAddress("192.168.159.254"), destination); } + @SmallTest public void testParseRtmNewNeigh() { final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_NEWNEIGH); byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. @@ -187,6 +190,7 @@ public class RtNetlinkNeighborMessageTest extends TestCase { assertEquals(InetAddress.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), destination); } + @SmallTest public void testParseRtmGetNeighResponse() { final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_GETNEIGH_RESPONSE); byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. @@ -211,6 +215,7 @@ public class RtNetlinkNeighborMessageTest extends TestCase { assertEquals(14, messageCount); } + @SmallTest public void testCreateRtmNewNeighMessage() { final int seqNo = 2635; final int ifIndex = 14; diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 4b3f99277e80e..46b64031ee8ac 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -70,7 +70,6 @@ import android.provider.Settings; import android.test.AndroidTestCase; import android.test.FlakyTest; import android.test.mock.MockContentResolver; -import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; import android.util.LogPrinter; @@ -196,6 +195,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } // Tests that IdleableHandlerThread works as expected. + @SmallTest public void testIdleableHandlerThread() { final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. @@ -220,6 +220,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } } + @SmallTest @FlakyTest(tolerance = 3) public void testNotWaitingForIdleCausesRaceConditions() { // Bring up a network that we can use to send messages to ConnectivityService. @@ -840,7 +841,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { return cv; } - @LargeTest + @SmallTest public void testLingering() throws Exception { verifyNoNetwork(); mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -880,7 +881,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyNoNetwork(); } - @LargeTest + @SmallTest public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception { // Test bringing up unvalidated WiFi mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); @@ -915,7 +916,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyNoNetwork(); } - @LargeTest + @SmallTest public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception { // Test bringing up unvalidated cellular. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -941,7 +942,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyNoNetwork(); } - @LargeTest + @SmallTest public void testUnlingeringDoesNotValidate() throws Exception { // Test bringing up unvalidated WiFi. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); @@ -969,7 +970,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { NET_CAPABILITY_VALIDATED)); } - @LargeTest + @SmallTest public void testCellularOutscoresWeakWifi() throws Exception { // Test bringing up validated cellular. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -995,7 +996,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyActiveNetwork(TRANSPORT_WIFI); } - @LargeTest + @SmallTest public void testReapingNetwork() throws Exception { // Test bringing up WiFi without NET_CAPABILITY_INTERNET. // Expect it to be torn down immediately because it satisfies no requests. @@ -1028,7 +1029,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { waitFor(cv); } - @LargeTest + @SmallTest public void testCellularFallback() throws Exception { // Test bringing up validated cellular. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -1066,7 +1067,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyActiveNetwork(TRANSPORT_WIFI); } - @LargeTest + @SmallTest public void testWiFiFallback() throws Exception { // Test bringing up unvalidated WiFi. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); @@ -1208,7 +1209,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } } - @LargeTest + @SmallTest public void testStateChangeNetworkCallbacks() throws Exception { final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); @@ -1591,7 +1592,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { handlerThread.quit(); } - @LargeTest + @SmallTest public void testNetworkFactoryRequests() throws Exception { tryNetworkFactoryRequests(NET_CAPABILITY_MMS); tryNetworkFactoryRequests(NET_CAPABILITY_SUPL); @@ -1611,7 +1612,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed. } - @LargeTest + @SmallTest public void testNoMutableNetworkRequests() throws Exception { PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0); NetworkRequest.Builder builder = new NetworkRequest.Builder(); @@ -1636,7 +1637,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } catch (IllegalArgumentException expected) {} } - @LargeTest + @SmallTest public void testMMSonWiFi() throws Exception { // Test bringing up cellular without MMS NetworkRequest gets reaped mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -1671,7 +1672,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyActiveNetwork(TRANSPORT_WIFI); } - @LargeTest + @SmallTest public void testMMSonCell() throws Exception { // Test bringing up cellular without MMS mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -1697,7 +1698,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyActiveNetwork(TRANSPORT_CELLULAR); } - @LargeTest + @SmallTest public void testCaptivePortal() { final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() @@ -1746,7 +1747,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); } - @LargeTest + @SmallTest public void testAvoidOrIgnoreCaptivePortals() { final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() @@ -1817,7 +1818,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { execptionCalled); } - @LargeTest + @SmallTest public void testRegisterDefaultNetworkCallback() throws Exception { final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); mCm.registerDefaultNetworkCallback(defaultNetworkCallback); @@ -1878,7 +1879,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } } - @LargeTest + @SmallTest public void testRequestCallbackUpdates() throws Exception { // File a network request for mobile. final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback(); @@ -2519,6 +2520,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { return mWiFiNetworkAgent.getNetwork(); } + @SmallTest public void testPacketKeepalives() throws Exception { InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index bce5787ed9a5f..77956be66c9e8 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -24,6 +24,7 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkMisc; +import android.test.suitebuilder.annotation.SmallTest; import android.text.format.DateUtils; import com.android.internal.R; import com.android.server.ConnectivityService; @@ -70,6 +71,7 @@ public class LingerMonitorTest extends TestCase { mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, HIGH_RATE_LIMIT); } + @SmallTest public void testTransitions() { setNotificationSwitch(transition(WIFI, CELLULAR)); NetworkAgentInfo nai1 = wifiNai(100); @@ -79,6 +81,7 @@ public class LingerMonitorTest extends TestCase { assertFalse(mMonitor.isNotificationEnabled(nai2, nai1)); } + @SmallTest public void testNotificationOnLinger() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -89,6 +92,7 @@ public class LingerMonitorTest extends TestCase { verifyNotification(from, to); } + @SmallTest public void testToastOnLinger() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); @@ -99,6 +103,7 @@ public class LingerMonitorTest extends TestCase { verifyToast(from, to); } + @SmallTest public void testNotificationClearedAfterDisconnect() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -112,6 +117,7 @@ public class LingerMonitorTest extends TestCase { verify(mNotifier, times(1)).clearNotification(100); } + @SmallTest public void testNotificationClearedAfterSwitchingBack() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -125,6 +131,7 @@ public class LingerMonitorTest extends TestCase { verify(mNotifier, times(1)).clearNotification(100); } + @SmallTest public void testUniqueToast() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); @@ -142,6 +149,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testMultipleNotifications() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -160,6 +168,7 @@ public class LingerMonitorTest extends TestCase { verifyNotification(wifi2, cell); } + @SmallTest public void testRateLimiting() throws InterruptedException { mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, LOW_RATE_LIMIT); @@ -185,6 +194,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testDailyLimiting() throws InterruptedException { mMonitor = new TestableLingerMonitor(mCtx, mNotifier, LOW_DAILY_LIMIT, HIGH_RATE_LIMIT); @@ -211,6 +221,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testUniqueNotification() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -227,6 +238,7 @@ public class LingerMonitorTest extends TestCase { verifyNotification(from, to); } + @SmallTest public void testIgnoreNeverValidatedNetworks() { setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); setNotificationSwitch(transition(WIFI, CELLULAR)); @@ -238,6 +250,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testIgnoreCurrentlyValidatedNetworks() { setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); setNotificationSwitch(transition(WIFI, CELLULAR)); @@ -249,6 +262,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testNoNotificationType() { setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); setNotificationSwitch(); @@ -259,6 +273,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testNoTransitionToNotify() { setNotificationType(LingerMonitor.NOTIFY_TYPE_NONE); setNotificationSwitch(transition(WIFI, CELLULAR)); @@ -269,6 +284,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testDifferentTransitionToNotify() { setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); setNotificationSwitch(transition(CELLULAR, WIFI)); diff --git a/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java b/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java index 5f84ea1bfd96b..5981f48e7ccd1 100644 --- a/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java +++ b/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java @@ -20,6 +20,7 @@ import android.content.Context; import android.net.ConnectivityMetricsEvent; import android.os.Bundle; import android.os.RemoteException; +import android.test.suitebuilder.annotation.SmallTest; import static android.net.ConnectivityMetricsEvent.Reference; import junit.framework.TestCase; @@ -67,12 +68,14 @@ public class MetricsLoggerServiceTest extends TestCase { mService.onStart(); } + @SmallTest public void testGetNoEvents() throws Exception { Reference r = new Reference(0); assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r)); assertEquals(0, r.getValue()); } + @SmallTest public void testLogAndGetEvents() throws Exception { mService.mBinder.logEvents(EVENTS); @@ -85,6 +88,7 @@ public class MetricsLoggerServiceTest extends TestCase { assertEquals(N_EVENTS, r.getValue()); } + @SmallTest public void testLogOneByOne() throws Exception { for (ConnectivityMetricsEvent ev : EVENTS) { mService.mBinder.logEvent(ev); @@ -99,6 +103,7 @@ public class MetricsLoggerServiceTest extends TestCase { assertEquals(N_EVENTS, r.getValue()); } + @SmallTest public void testInterleavedLogAndGet() throws Exception { mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 0, 3)); @@ -117,6 +122,7 @@ public class MetricsLoggerServiceTest extends TestCase { assertEquals(N_EVENTS, r.getValue()); } + @SmallTest public void testMultipleGetAll() throws Exception { mService.mBinder.logEvents(Arrays.copyOf(EVENTS, 3)); @@ -131,6 +137,7 @@ public class MetricsLoggerServiceTest extends TestCase { assertEquals(N_EVENTS, r2.getValue()); } + @SmallTest public void testLogAndDumpConcurrently() throws Exception { for (int i = 0; i < 50; i++) { mContext = null; diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java index af4a374bffddf..2bb62bbdcf595 100644 --- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java +++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java @@ -23,6 +23,7 @@ import android.net.metrics.DnsEvent; import android.net.metrics.INetdEventListener; import android.net.metrics.IpConnectivityLog; import android.os.RemoteException; +import android.test.suitebuilder.annotation.SmallTest; import junit.framework.TestCase; import org.junit.Before; @@ -83,6 +84,7 @@ public class NetdEventListenerServiceTest extends TestCase { verify(mCm, times(1)).registerNetworkCallback(any(), mCallbackCaptor.capture()); } + @SmallTest public void testOneBatch() throws Exception { log(105, LATENCIES); log(106, Arrays.copyOf(LATENCIES, BATCH_SIZE - 1)); // one lookup short of a batch event @@ -97,6 +99,7 @@ public class NetdEventListenerServiceTest extends TestCase { new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES)); } + @SmallTest public void testSeveralBatches() throws Exception { log(105, LATENCIES); log(106, LATENCIES); @@ -110,6 +113,7 @@ public class NetdEventListenerServiceTest extends TestCase { new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES)); } + @SmallTest public void testBatchAndNetworkLost() throws Exception { byte[] eventTypes = Arrays.copyOf(EVENT_TYPES, 20); byte[] returnCodes = Arrays.copyOf(RETURN_CODES, 20); @@ -126,6 +130,7 @@ public class NetdEventListenerServiceTest extends TestCase { new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES)); } + @SmallTest public void testConcurrentBatchesAndDumps() throws Exception { final long stop = System.currentTimeMillis() + 100; final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null")); @@ -147,6 +152,7 @@ public class NetdEventListenerServiceTest extends TestCase { new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES)); } + @SmallTest public void testConcurrentBatchesAndNetworkLoss() throws Exception { logAsync(105, LATENCIES); Thread.sleep(10L); From 612f058d48bb57a2f375b2bf34a1e5049571f1d2 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Wed, 7 Dec 2016 14:39:05 +0900 Subject: [PATCH 5/9] Removing bogus file added by mistake This patch deletes a bogus file added by mistake in the change with commit hash 147aa6d53bc1e9f8a3632553abcf936023806e1d. Test: no code change. Bug: 32198726 Change-Id: Iffc6b3a5ebd854dc81d537576a4405955abacba7 --- ] | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 ] diff --git a/] b/] deleted file mode 100644 index 5619151c7ee3e..0000000000000 --- a/] +++ /dev/null @@ -1,12 +0,0 @@ -NetworkNotificationManager: logging improvements - -TODO: squash me -# Please enter the commit message for your changes. Lines starting -# with '#' will be ignored, and an empty message aborts the commit. -# On branch notification_tagging -# Your branch is ahead of 'goog/master' by 2 commits. -# (use "git push" to publish your local commits) -# -# Changes to be committed: -# modified: services/core/java/com/android/server/connectivity/NetworkNotificationManager.java -# From 3daf708e3cdc07bb2c98346c90589212ddff3479 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Thu, 10 Nov 2016 22:45:56 +0900 Subject: [PATCH 6/9] Fix flaky IpPrefixTest. Test: IpPrefixTest passes Bug: 32561414 (cherry picked from commit 32c687040301cb3601fd110281a742159a963aa9) Change-Id: I42928da87f7f336900b3a95ebbf28563864da8d4 --- .../src/android/net/IpPrefixTest.java | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/core/tests/coretests/src/android/net/IpPrefixTest.java b/core/tests/coretests/src/android/net/IpPrefixTest.java index fcc638960bb8a..4f2387dcf5c13 100644 --- a/core/tests/coretests/src/android/net/IpPrefixTest.java +++ b/core/tests/coretests/src/android/net/IpPrefixTest.java @@ -18,14 +18,14 @@ package android.net; import android.net.IpPrefix; import android.os.Parcel; -import static android.test.MoreAsserts.assertNotEqual; import android.test.suitebuilder.annotation.SmallTest; - -import static org.junit.Assert.assertArrayEquals; import java.net.InetAddress; import java.util.Random; import junit.framework.TestCase; +import static android.test.MoreAsserts.assertNotEqual; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; public class IpPrefixTest extends TestCase { @@ -242,25 +242,42 @@ public class IpPrefixTest extends TestCase { @SmallTest public void testHashCode() { - IpPrefix p; - int oldCode = -1; + IpPrefix p = new IpPrefix(new byte[4], 0); Random random = new Random(); for (int i = 0; i < 100; i++) { + final IpPrefix oldP = p; if (random.nextBoolean()) { // IPv4. byte[] b = new byte[4]; random.nextBytes(b); p = new IpPrefix(b, random.nextInt(33)); - assertNotEqual(oldCode, p.hashCode()); - oldCode = p.hashCode(); } else { // IPv6. byte[] b = new byte[16]; random.nextBytes(b); p = new IpPrefix(b, random.nextInt(129)); - assertNotEqual(oldCode, p.hashCode()); - oldCode = p.hashCode(); } + if (p.equals(oldP)) { + assertEquals(p.hashCode(), oldP.hashCode()); + } + if (p.hashCode() != oldP.hashCode()) { + assertNotEqual(p, oldP); + } + } + } + + @SmallTest + public void testHashCodeIsNotConstant() { + IpPrefix[] prefixes = { + new IpPrefix("2001:db8:f00::ace:d00d/127"), + new IpPrefix("192.0.2.0/23"), + new IpPrefix("::/0"), + new IpPrefix("0.0.0.0/0"), + }; + for (int i = 0; i < prefixes.length; i++) { + for (int j = i + 1; j < prefixes.length; j++) { + assertNotEqual(prefixes[i].hashCode(), prefixes[j].hashCode()); + } } } From 6814bd1afe39d13aad948b283fac64ca88bbc9d2 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Mon, 21 Nov 2016 13:50:05 +0900 Subject: [PATCH 7/9] Captive portal systel log improvements This patch improves system logging around captive portal detection to make inspection of bug reports sligthly easier: - NetworkMonitor now logs by default CMD_CAPTIVE_PORTAL_RECHECK and CMD_CAPTIVE_PORTAL_APP_FINISHED. Other system logs are kept off with a new VDBG boolean contant, - NetworkNotificationManager now prints the notification id at notification time. This allows to easily correlate show and clear. - errors in NetworkNotificationManager are logged as Throwable instead of through their implicit toString() method. Test: $ runtest frameworks-net Bug: 32198726 (cherry picked from commit 8b025bf108c729156b40159038befa0e6c5bebce) Change-Id: I1eaab5ea702063dde3e23324d3a1b3dc172c5ac5 --- .../android/server/connectivity/NetworkMonitor.java | 11 ++++++----- .../connectivity/NetworkNotificationManager.java | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index ea2cf5fb4a7ef..5e98859141697 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -80,7 +80,8 @@ import java.util.concurrent.TimeUnit; */ public class NetworkMonitor extends StateMachine { private static final String TAG = NetworkMonitor.class.getSimpleName(); - private static final boolean DBG = false; + private static final boolean DBG = true; + private static final boolean VDBG = false; // Default configuration values for captive portal detection probes. // TODO: append a random length parameter to the default HTTPS url. @@ -954,7 +955,7 @@ public class NetworkMonitor extends StateMachine { latencyBroadcast.putExtra(EXTRA_SSID, currentWifiInfo.getSSID()); latencyBroadcast.putExtra(EXTRA_BSSID, currentWifiInfo.getBSSID()); } else { - if (DBG) logw("network info is TYPE_WIFI but no ConnectionInfo found"); + if (VDBG) logw("network info is TYPE_WIFI but no ConnectionInfo found"); return; } break; @@ -967,8 +968,8 @@ public class NetworkMonitor extends StateMachine { if (cellInfo.isRegistered()) { numRegisteredCellInfo++; if (numRegisteredCellInfo > 1) { - log("more than one registered CellInfo. Can't " + - "tell which is active. Bailing."); + if (VDBG) logw("more than one registered CellInfo." + + " Can't tell which is active. Bailing."); return; } if (cellInfo instanceof CellInfoCdma) { @@ -984,7 +985,7 @@ public class NetworkMonitor extends StateMachine { CellIdentityWcdma cellId = ((CellInfoWcdma) cellInfo).getCellIdentity(); latencyBroadcast.putExtra(EXTRA_CELL_ID, cellId); } else { - if (DBG) logw("Registered cellinfo is unrecognized"); + if (VDBG) logw("Registered cellinfo is unrecognized"); return; } } diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index f7b01be48d887..c6bf4c5fcd6a4 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -114,7 +114,7 @@ public class NetworkNotificationManager { } if (DBG) { - Slog.d(TAG, "showNotification " + notifyType + Slog.d(TAG, "showNotification id=" + id + " " + notifyType + " transportType=" + getTransportName(transportType) + " extraInfo=" + extraInfo + " highPriority=" + highPriority); } @@ -187,7 +187,7 @@ public class NetworkNotificationManager { try { mNotificationManager.notifyAsUser(NOTIFICATION_ID, id, notification, UserHandle.ALL); } catch (NullPointerException npe) { - Slog.d(TAG, "setNotificationVisible: visible notificationManager npe=" + npe); + Slog.d(TAG, "setNotificationVisible: visible notificationManager error", npe); } } @@ -198,7 +198,7 @@ public class NetworkNotificationManager { try { mNotificationManager.cancelAsUser(NOTIFICATION_ID, id, UserHandle.ALL); } catch (NullPointerException npe) { - Slog.d(TAG, "setNotificationVisible: cancel notificationManager npe=" + npe); + Slog.d(TAG, "setNotificationVisible: cancel notificationManager error", npe); } } From ef78d27703a3ad6c8b13061e3dbeeeeaf0ade6e0 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Tue, 6 Dec 2016 15:36:30 +0900 Subject: [PATCH 8/9] Logging improvements in CaptivePortalLoginActivity Logging improvements to help debugging captive portal issues. Test: manually tested Bug: 33126342 (cherry picked from commit 87de0c206709d3a170649b535a973de8f9c0fb0c) Change-Id: I52425b849412f6bd5c5ca1f0be7a49cc772497eb --- .../CaptivePortalLoginActivity.java | 78 +++++++++++++------ 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java index bb8eb2cd07977..03f0b4d5d5da6 100644 --- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java +++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java @@ -55,12 +55,14 @@ import java.lang.reflect.Method; import java.util.Random; public class CaptivePortalLoginActivity extends Activity { - private static final String TAG = "CaptivePortalLogin"; + private static final String TAG = CaptivePortalLoginActivity.class.getSimpleName(); + private static final boolean DBG = true; + private static final int SOCKET_TIMEOUT_MS = 10000; private enum Result { DISMISSED, UNWANTED, WANTED_AS_IS }; - private URL mURL; + private URL mUrl; private Network mNetwork; private CaptivePortal mCaptivePortal; private NetworkCallback mNetworkCallback; @@ -72,17 +74,18 @@ public class CaptivePortalLoginActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mCm = ConnectivityManager.from(this); - String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL); - if (url == null) url = mCm.getCaptivePortalServerUrl(); - try { - mURL = new URL(url); - } catch (MalformedURLException e) { - // System misconfigured, bail out in a way that at least provides network access. - Log.e(TAG, "Invalid captive portal URL, url=" + url); - done(Result.WANTED_AS_IS); - } mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK); mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL); + mUrl = getUrl(); + if (mUrl == null) { + // getUrl() failed to parse the url provided in the intent: bail out in a way that + // at least provides network access. + done(Result.WANTED_AS_IS); + return; + } + if (DBG) { + Log.d(TAG, String.format("onCreate for %s", mUrl.toString())); + } // Also initializes proxy system properties. mCm.bindProcessToNetwork(mNetwork); @@ -149,6 +152,9 @@ public class CaptivePortalLoginActivity extends Activity { } private void done(Result result) { + if (DBG) { + Log.d(TAG, String.format("Result %s for %s", result.name(), mUrl.toString())); + } if (mNetworkCallback != null) { mCm.unregisterNetworkCallback(mNetworkCallback); mNetworkCallback = null; @@ -185,22 +191,31 @@ public class CaptivePortalLoginActivity extends Activity { @Override public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); - if (id == R.id.action_use_network) { - done(Result.WANTED_AS_IS); - return true; + final Result result; + final String action; + final int id = item.getItemId(); + switch (id) { + case R.id.action_use_network: + result = Result.WANTED_AS_IS; + action = "USE_NETWORK"; + break; + case R.id.action_do_not_use_network: + result = Result.UNWANTED; + action = "DO_NOT_USE_NETWORK"; + break; + default: + return super.onOptionsItemSelected(item); } - if (id == R.id.action_do_not_use_network) { - done(Result.UNWANTED); - return true; + if (DBG) { + Log.d(TAG, String.format("onOptionsItemSelect %s for %s", action, mUrl.toString())); } - return super.onOptionsItemSelected(item); + done(result); + return true; } @Override public void onDestroy() { super.onDestroy(); - if (mNetworkCallback != null) { mCm.unregisterNetworkCallback(mNetworkCallback); mNetworkCallback = null; @@ -215,10 +230,27 @@ public class CaptivePortalLoginActivity extends Activity { } catch (InterruptedException e) { } } - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(mURL.toString()))); + final String url = mUrl.toString(); + if (DBG) { + Log.d(TAG, "starting activity with intent ACTION_VIEW for " + url); + } + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); } } + private URL getUrl() { + String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL); + if (url == null) { + url = mCm.getCaptivePortalServerUrl(); + } + try { + return new URL(url); + } catch (MalformedURLException e) { + Log.e(TAG, "Invalid captive portal URL " + url); + } + return null; + } + private void testForCaptivePortal() { new Thread(new Runnable() { public void run() { @@ -230,7 +262,7 @@ public class CaptivePortalLoginActivity extends Activity { HttpURLConnection urlConnection = null; int httpResponseCode = 500; try { - urlConnection = (HttpURLConnection) mURL.openConnection(); + urlConnection = (HttpURLConnection) mUrl.openConnection(); urlConnection.setInstanceFollowRedirects(false); urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS); urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS); @@ -292,7 +324,7 @@ public class CaptivePortalLoginActivity extends Activity { // settings. Now prompt the WebView read the Network-specific proxy settings. setWebViewProxy(); // Load the real page. - view.loadUrl(mURL.toString()); + view.loadUrl(mUrl.toString()); return; } else if (mPagesLoaded == 2) { // Prevent going back to empty first page. From 88932754ffdcbffb3cb43e03991e5eb598c10458 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Wed, 14 Dec 2016 08:23:40 +0900 Subject: [PATCH 9/9] Captive portals: login activity probes like NetworkMonitor This patch changes CaptivePortalLoginActivity captive portal test to be consistent with NetworkMonitor by: - using Network.java to open the http connection. - adding a UserAgent property to the request header. Test: manually tested. Bug: 32369183 (cherry picked from commit cdf3ba48ccef0f9c6ca8724c1c106df0dd725ad0) Change-Id: I559eb0497475daad758ba3b3395225dcd0a27a57 --- core/java/android/net/ConnectivityManager.java | 7 +++++++ .../captiveportallogin/CaptivePortalLoginActivity.java | 9 ++++++++- .../com/android/server/connectivity/NetworkMonitor.java | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 51431ebfaf146..042481f1727ee 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -222,6 +222,13 @@ public class ConnectivityManager { */ public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL"; + /** + * Key for passing a user agent string to the captive portal login activity. + * {@hide} + */ + public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = + "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; + /** * Broadcast action to indicate the change of data activity status * (idle or active) on a network in a recent period. diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java index 03f0b4d5d5da6..23a8655a3bb68 100644 --- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java +++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java @@ -63,6 +63,7 @@ public class CaptivePortalLoginActivity extends Activity { private enum Result { DISMISSED, UNWANTED, WANTED_AS_IS }; private URL mUrl; + private String mUserAgent; private Network mNetwork; private CaptivePortal mCaptivePortal; private NetworkCallback mNetworkCallback; @@ -76,6 +77,8 @@ public class CaptivePortalLoginActivity extends Activity { mCm = ConnectivityManager.from(this); mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK); mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL); + mUserAgent = getIntent().getParcelableExtra( + ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT); mUrl = getUrl(); if (mUrl == null) { // getUrl() failed to parse the url provided in the intent: bail out in a way that @@ -252,6 +255,7 @@ public class CaptivePortalLoginActivity extends Activity { } private void testForCaptivePortal() { + // TODO: reuse NetworkMonitor facilities for consistent captive portal detection. new Thread(new Runnable() { public void run() { // Give time for captive portal to open. @@ -262,11 +266,14 @@ public class CaptivePortalLoginActivity extends Activity { HttpURLConnection urlConnection = null; int httpResponseCode = 500; try { - urlConnection = (HttpURLConnection) mUrl.openConnection(); + urlConnection = (HttpURLConnection) mNetwork.openConnection(mUrl); urlConnection.setInstanceFollowRedirects(false); urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS); urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS); urlConnection.setUseCaches(false); + if (mUserAgent != null) { + urlConnection.setRequestProperty("User-Agent", mUserAgent); + } urlConnection.getInputStream(); httpResponseCode = urlConnection.getResponseCode(); } catch (IOException e) { diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index 5e98859141697..9ffe2b78a0957 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -433,6 +433,8 @@ public class NetworkMonitor extends StateMachine { })); intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, mLastPortalProbeResult.detectUrl); + intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT, + getCaptivePortalUserAgent(mContext)); intent.setFlags( Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivityAsUser(intent, UserHandle.CURRENT);