diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index b449e72bd0..ac1fd55488 100755 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -7919,7 +7919,8 @@ public class ConnectivityService extends IConnectivityManager.Stub return captivePortalBuilder.build(); } - private String makeNflogPrefix(String iface, long networkHandle) { + @VisibleForTesting + static String makeNflogPrefix(String iface, long networkHandle) { // This needs to be kept in sync and backwards compatible with the decoding logic in // NetdEventListenerService, which is non-mainline code. return SdkLevel.isAtLeastU() ? (networkHandle + ":" + iface) : ("iface:" + iface); diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java index bd8ac06ab6..e041815996 100755 --- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java @@ -154,6 +154,7 @@ import static com.android.server.ConnectivityService.PREFERENCE_ORDER_OEM; import static com.android.server.ConnectivityService.PREFERENCE_ORDER_PROFILE; import static com.android.server.ConnectivityService.PREFERENCE_ORDER_VPN; import static com.android.server.ConnectivityService.createDeliveryGroupKeyForConnectivityAction; +import static com.android.server.ConnectivityService.makeNflogPrefix; import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType; import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackRegister; import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister; @@ -533,6 +534,10 @@ public class ConnectivityServiceTest { private static final int TEST_PACKAGE_UID = 123; private static final int TEST_PACKAGE_UID2 = 321; private static final int TEST_PACKAGE_UID3 = 456; + + private static final int PACKET_WAKEUP_MASK = 0xffff0000; + private static final int PACKET_WAKEUP_MARK = 0x88880000; + private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn"; private static final String INTERFACE_NAME = "interface"; @@ -1910,6 +1915,10 @@ public class ConnectivityServiceTest { doReturn(0).when(mResources).getInteger(R.integer.config_activelyPreferBadWifi); doReturn(true).when(mResources) .getBoolean(R.bool.config_cellular_radio_timesharing_capable); + doReturn(PACKET_WAKEUP_MASK).when(mResources).getInteger( + R.integer.config_networkWakeupPacketMask); + doReturn(PACKET_WAKEUP_MARK).when(mResources).getInteger( + R.integer.config_networkWakeupPacketMark); } // ConnectivityServiceDependencies is public to use Mockito.spy @@ -10393,6 +10402,16 @@ public class ConnectivityServiceTest { return event; } + private void verifyWakeupModifyInterface(String iface, boolean add) throws RemoteException { + if (add) { + verify(mMockNetd).wakeupAddInterface(eq(iface), anyString(), anyInt(), + anyInt()); + } else { + verify(mMockNetd).wakeupDelInterface(eq(iface), anyString(), anyInt(), + anyInt()); + } + } + private T verifyWithOrder(@Nullable InOrder inOrder, @NonNull T t) { if (inOrder != null) { return inOrder.verify(t); @@ -10619,6 +10638,11 @@ public class ConnectivityServiceTest { clat.interfaceRemoved(CLAT_MOBILE_IFNAME); networkCallback.assertNoCallback(); verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME); + + if (SdkLevel.isAtLeastU()) { + verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, false); + } + verifyNoMoreInteractions(mMockNetd); verifyNoMoreInteractions(mClatCoordinator); verifyNoMoreInteractions(mMockDnsResolver); @@ -10655,6 +10679,10 @@ public class ConnectivityServiceTest { assertRoutesAdded(cellNetId, stackedDefault); verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME); + if (SdkLevel.isAtLeastU()) { + verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, true); + } + // NAT64 prefix is removed. Expect that clat is stopped. mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent( cellNetId, PREFIX_OPERATION_REMOVED, kNat64PrefixString, 96)); @@ -10669,6 +10697,11 @@ public class ConnectivityServiceTest { cb -> cb.getLp().getStackedLinks().size() == 0); verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME); verify(mMockNetd, times(1)).interfaceGetCfg(CLAT_MOBILE_IFNAME); + + if (SdkLevel.isAtLeastU()) { + verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, false); + } + // Clean up. mCellAgent.disconnect(); networkCallback.expect(LOST, mCellAgent); @@ -10681,6 +10714,11 @@ public class ConnectivityServiceTest { } else { verify(mMockNetd, never()).setNetworkAllowlist(any()); } + + if (SdkLevel.isAtLeastU()) { + verifyWakeupModifyInterface(MOBILE_IFNAME, false); + } + verifyNoMoreInteractions(mMockNetd); verifyNoMoreInteractions(mClatCoordinator); reset(mMockNetd); @@ -10710,6 +10748,11 @@ public class ConnectivityServiceTest { verify(mMockNetd).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME); // assertRoutesAdded sees all calls since last mMockNetd reset, so expect IPv6 routes again. assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default, stackedDefault); + + if (SdkLevel.isAtLeastU()) { + verifyWakeupModifyInterface(MOBILE_IFNAME, true); + } + reset(mMockNetd); reset(mClatCoordinator); @@ -10718,6 +10761,11 @@ public class ConnectivityServiceTest { networkCallback.expect(LOST, mCellAgent); networkCallback.assertNoCallback(); verifyClatdStop(null /* inOrder */, MOBILE_IFNAME); + + if (SdkLevel.isAtLeastU()) { + verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, false); + } + verify(mMockNetd).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(), eq(Integer.toString(TRANSPORT_CELLULAR))); verify(mMockNetd).networkDestroy(cellNetId); @@ -10726,6 +10774,11 @@ public class ConnectivityServiceTest { } else { verify(mMockNetd, never()).setNetworkAllowlist(any()); } + + if (SdkLevel.isAtLeastU()) { + verifyWakeupModifyInterface(MOBILE_IFNAME, false); + } + verifyNoMoreInteractions(mMockNetd); verifyNoMoreInteractions(mClatCoordinator); @@ -17671,4 +17724,48 @@ public class ConnectivityServiceTest { info.setExtraInfo("test_info"); assertEquals("0;2;test_info", createDeliveryGroupKeyForConnectivityAction(info)); } + + @Test + public void testNetdWakeupAddInterfaceForWifiTransport() throws Exception { + final LinkProperties wifiLp = new LinkProperties(); + wifiLp.setInterfaceName(WIFI_IFNAME); + mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp); + mWiFiAgent.connect(false /* validated */); + + final String expectedPrefix = makeNflogPrefix(WIFI_IFNAME, + mWiFiAgent.getNetwork().getNetworkHandle()); + verify(mMockNetd).wakeupAddInterface(WIFI_IFNAME, expectedPrefix, PACKET_WAKEUP_MARK, + PACKET_WAKEUP_MASK); + } + + @Test + public void testNetdWakeupAddInterfaceForCellularTransport() throws Exception { + final LinkProperties cellLp = new LinkProperties(); + cellLp.setInterfaceName(MOBILE_IFNAME); + mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); + mCellAgent.connect(false /* validated */); + + if (SdkLevel.isAtLeastU()) { + final String expectedPrefix = makeNflogPrefix(MOBILE_IFNAME, + mCellAgent.getNetwork().getNetworkHandle()); + verify(mMockNetd).wakeupAddInterface(MOBILE_IFNAME, expectedPrefix, PACKET_WAKEUP_MARK, + PACKET_WAKEUP_MASK); + } else { + verify(mMockNetd, never()).wakeupAddInterface(eq(MOBILE_IFNAME), anyString(), anyInt(), + anyInt()); + } + } + + @Test + public void testNetdWakeupAddInterfaceForEthernetTransport() throws Exception { + final String ethernetIface = "eth42"; + + final LinkProperties ethLp = new LinkProperties(); + ethLp.setInterfaceName(ethernetIface); + mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET, ethLp); + mEthernetAgent.connect(false /* validated */); + + verify(mMockNetd, never()).wakeupAddInterface(eq(ethernetIface), anyString(), anyInt(), + anyInt()); + } } diff --git a/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java index f4b6464a0b..d6676622b4 100644 --- a/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java +++ b/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java @@ -24,6 +24,7 @@ import static com.android.testutils.MiscAsserts.assertStringContains; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -41,6 +42,8 @@ import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpCon import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRunner; +import libcore.util.EmptyArray; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -60,7 +63,8 @@ public class NetdEventListenerServiceTest { private static final String EXAMPLE_IPV4 = "192.0.2.1"; private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1"; - private static final long NET_HANDLE = new Network(5391).getNetworkHandle(); + private static final Network TEST_WIFI_NETWORK = new Network(5391); + private static final Network TEST_CELL_NETWORK = new Network(5832); private static final byte[] MAC_ADDR = {(byte)0x84, (byte)0xc9, (byte)0xb2, (byte)0x6a, (byte)0xed, (byte)0x4b}; @@ -78,6 +82,8 @@ public class NetdEventListenerServiceTest { public void setUp() { mCm = mock(ConnectivityManager.class); mService = new NetdEventListenerService(mCm); + doReturn(CAPABILITIES_WIFI).when(mCm).getNetworkCapabilities(TEST_WIFI_NETWORK); + doReturn(CAPABILITIES_CELL).when(mCm).getNetworkCapabilities(TEST_CELL_NETWORK); } @Test @@ -111,19 +117,25 @@ public class NetdEventListenerServiceTest { wakeupEvent(iface, uids[5], v4, tcp, mac, srcIp, dstIp, sport, dport, now); wakeupEvent(iface, uids[6], v6, udp, mac, srcIp6, dstIp6, sport, dport, now); wakeupEvent(iface, uids[7], v6, tcp, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent(iface, uids[8], v6, udp, mac, srcIp6, dstIp6, sport, dport, now); + wakeupEvent("rmnet0", uids[8], v6, udp, EmptyArray.BYTE, srcIp6, dstIp6, sport, dport, now, + TEST_CELL_NETWORK); String[] events2 = remove(listNetdEvent(), baseline); - int expectedLength2 = uids.length + 1; // +1 for the WakeupStats line + int expectedLength2 = uids.length + 2; // +2 for the WakeupStats headers assertEquals(expectedLength2, events2.length); + assertStringContains(events2[0], "WakeupStats"); - assertStringContains(events2[0], "wlan0"); - assertStringContains(events2[0], "0x800"); + assertStringContains(events2[0], "rmnet0"); assertStringContains(events2[0], "0x86dd"); + + assertStringContains(events2[1], "WakeupStats"); + assertStringContains(events2[1], "wlan0"); + assertStringContains(events2[1], "0x800"); + assertStringContains(events2[1], "0x86dd"); for (int i = 0; i < uids.length; i++) { - String got = events2[i+1]; + String got = events2[i + 2]; assertStringContains(got, "WakeupEvent"); - assertStringContains(got, "wlan0"); + assertStringContains(got, ((i == 8) ? "rmnet0" : "wlan0")); assertStringContains(got, "uid: " + uids[i]); } @@ -134,11 +146,13 @@ public class NetdEventListenerServiceTest { } String[] events3 = remove(listNetdEvent(), baseline); - int expectedLength3 = BUFFER_LENGTH + 1; // +1 for the WakeupStats line + int expectedLength3 = BUFFER_LENGTH + 2; // +2 for the WakeupStats headers assertEquals(expectedLength3, events3.length); - assertStringContains(events2[0], "WakeupStats"); - assertStringContains(events2[0], "wlan0"); - for (int i = 1; i < expectedLength3; i++) { + assertStringContains(events3[0], "WakeupStats"); + assertStringContains(events3[0], "rmnet0"); + assertStringContains(events3[1], "WakeupStats"); + assertStringContains(events3[1], "wlan0"); + for (int i = 2; i < expectedLength3; i++) { String got = events3[i]; assertStringContains(got, "WakeupEvent"); assertStringContains(got, "wlan0"); @@ -173,19 +187,24 @@ public class NetdEventListenerServiceTest { final int icmp6 = 58; wakeupEvent("wlan0", 1000, v4, tcp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent("rmnet0", 10123, v4, tcp, mac, srcIp, dstIp, sport, dport, now); + wakeupEvent("rmnet0", 10123, v4, tcp, mac, srcIp, dstIp, sport, dport, now, + TEST_CELL_NETWORK); wakeupEvent("wlan0", 1000, v4, udp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent("rmnet0", 10008, v4, tcp, mac, srcIp, dstIp, sport, dport, now); + wakeupEvent("rmnet0", 10008, v4, tcp, EmptyArray.BYTE, srcIp, dstIp, sport, dport, now, + TEST_CELL_NETWORK); wakeupEvent("wlan0", -1, v6, icmp6, mac, srcIp6, dstIp6, sport, dport, now); wakeupEvent("wlan0", 10008, v4, tcp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent("rmnet0", 1000, v4, tcp, mac, srcIp, dstIp, sport, dport, now); + wakeupEvent("rmnet0", 1000, v4, tcp, mac, srcIp, dstIp, sport, dport, now, + TEST_CELL_NETWORK); wakeupEvent("wlan0", 10004, v4, udp, mac, srcIp, dstIp, sport, dport, now); wakeupEvent("wlan0", 1000, v6, tcp, mac, srcIp6, dstIp6, sport, dport, now); wakeupEvent("wlan0", 0, v6, udp, mac, srcIp6, dstIp6, sport, dport, now); wakeupEvent("wlan0", -1, v6, icmp6, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent("rmnet0", 10052, v4, tcp, mac, srcIp, dstIp, sport, dport, now); + wakeupEvent("rmnet0", 10052, v4, tcp, mac, srcIp, dstIp, sport, dport, now, + TEST_CELL_NETWORK); wakeupEvent("wlan0", 0, v6, udp, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent("rmnet0", 1000, v6, tcp, mac, srcIp6, dstIp6, sport, dport, now); + wakeupEvent("rmnet0", 1000, v6, tcp, null, srcIp6, dstIp6, sport, dport, now, + TEST_CELL_NETWORK); wakeupEvent("wlan0", 1010, v4, udp, mac, srcIp, dstIp, sport, dport, now); String got = flushStatistics(); @@ -214,7 +233,7 @@ public class NetdEventListenerServiceTest { " >", " l2_broadcast_count: 0", " l2_multicast_count: 0", - " l2_unicast_count: 5", + " l2_unicast_count: 3", " no_uid_wakeups: 0", " non_application_wakeups: 0", " root_wakeups: 0", @@ -499,8 +518,13 @@ public class NetdEventListenerServiceTest { } void wakeupEvent(String iface, int uid, int ether, int ip, byte[] mac, String srcIp, - String dstIp, int sport, int dport, long now) throws Exception { - String prefix = NET_HANDLE + ":" + iface; + String dstIp, int sport, int dport, long now) { + wakeupEvent(iface, uid, ether, ip, mac, srcIp, dstIp, sport, dport, now, TEST_WIFI_NETWORK); + } + + void wakeupEvent(String iface, int uid, int ether, int ip, byte[] mac, String srcIp, + String dstIp, int sport, int dport, long now, Network network) { + String prefix = network.getNetworkHandle() + ":" + iface; mService.onWakeupEvent(prefix, uid, ether, ip, mac, srcIp, dstIp, sport, dport, now); }