Snap for 12100605 from 74d887508e415139efb43cf311aae382789eff0a to mainline-os-statsd-release Change-Id: Iff5f90c40ea585e8b779ec92f89b65c4962cad68
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java index dd55165..c8e43d0 100644 --- a/src/android/net/apf/ApfFilter.java +++ b/src/android/net/apf/ApfFilter.java
@@ -288,7 +288,6 @@ private final boolean mDrop802_3Frames; private final int[] mEthTypeBlackList; - private final Clock mClock; private final ApfCounterTracker mApfCounterTracker = new ApfCounterTracker(); @GuardedBy("this") private final long mSessionStartMs; @@ -389,21 +388,13 @@ public ApfFilter(Context context, ApfConfiguration config, InterfaceParams ifParams, IpClientCallbacksWrapper ipClientCallback, NetworkQuirkMetrics networkQuirkMetrics) { this(context, config, ifParams, ipClientCallback, networkQuirkMetrics, - new Dependencies(context), new Clock()); + new Dependencies(context)); } @VisibleForTesting public ApfFilter(Context context, ApfConfiguration config, InterfaceParams ifParams, IpClientCallbacksWrapper ipClientCallback, NetworkQuirkMetrics networkQuirkMetrics, Dependencies dependencies) { - this(context, config, ifParams, ipClientCallback, networkQuirkMetrics, dependencies, - new Clock()); - } - - @VisibleForTesting - public ApfFilter(Context context, ApfConfiguration config, InterfaceParams ifParams, - IpClientCallbacksWrapper ipClientCallback, NetworkQuirkMetrics networkQuirkMetrics, - Dependencies dependencies, Clock clock) { mApfVersionSupported = config.apfVersionSupported; mApfRamSize = config.apfRamSize; mInstallableProgramSizeClamp = config.installableProgramSizeClamp; @@ -429,8 +420,7 @@ mNetworkQuirkMetrics = networkQuirkMetrics; mIpClientRaInfoMetrics = dependencies.getIpClientRaInfoMetrics(); mApfSessionInfoMetrics = dependencies.getApfSessionInfoMetrics(); - mClock = clock; - mSessionStartMs = mClock.elapsedRealtime(); + mSessionStartMs = dependencies.elapsedRealtime(); mMinMetricsSessionDurationMs = config.minMetricsSessionDurationMs; mHasClat = config.hasClatInterface; @@ -455,7 +445,9 @@ mDependencies.onApfFilterCreated(this); // mReceiveThread is created in startFilter() and halted in shutdown(). - mDependencies.onThreadCreated(mReceiveThread); + if (mReceiveThread != null) { + mDependencies.onThreadCreated(mReceiveThread); + } } /** @@ -468,6 +460,31 @@ mContext = context; } + /** + * Create a socket to read RAs. + */ + @Nullable + public FileDescriptor createRaReaderSocket(int ifIndex) { + FileDescriptor socket; + try { + socket = Os.socket(AF_PACKET, SOCK_RAW | SOCK_CLOEXEC, 0); + NetworkStackUtils.attachRaFilter(socket); + SocketAddress addr = makePacketSocketAddress(ETH_P_IPV6, ifIndex); + Os.bind(socket, addr); + } catch (SocketException | ErrnoException e) { + Log.wtf(TAG, "Error starting filter", e); + return null; + } + return socket; + } + + /** + * Get elapsedRealtime. + */ + public long elapsedRealtime() { + return SystemClock.elapsedRealtime(); + } + /** Add receiver for detecting doze mode change */ public void addDeviceIdleReceiver(@NonNull final BroadcastReceiver receiver) { final IntentFilter intentFilter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED); @@ -621,24 +638,17 @@ // Install basic filters installNewProgramLocked(); } - FileDescriptor socket; - try { - socket = Os.socket(AF_PACKET, SOCK_RAW | SOCK_CLOEXEC, 0); - NetworkStackUtils.attachRaFilter(socket); - SocketAddress addr = makePacketSocketAddress(ETH_P_IPV6, mInterfaceParams.index); - Os.bind(socket, addr); - } catch(SocketException|ErrnoException e) { - Log.wtf(TAG, "Error starting filter", e); - return; + FileDescriptor socket = mDependencies.createRaReaderSocket(mInterfaceParams.index); + if (socket != null) { + mReceiveThread = new ReceiveThread(socket); + mReceiveThread.start(); } - mReceiveThread = new ReceiveThread(socket); - mReceiveThread.start(); } // Returns seconds since device boot. @VisibleForTesting protected int secondsSinceBoot() { - return (int) (mClock.elapsedRealtime() / DateUtils.SECOND_IN_MILLIS); + return (int) (mDependencies.elapsedRealtime() / DateUtils.SECOND_IN_MILLIS); } public static class InvalidRaException extends Exception { @@ -2248,7 +2258,7 @@ */ @GuardedBy("this") @VisibleForTesting - protected ApfV4GeneratorBase<?> emitPrologueLocked() throws IllegalInstructionException { + public ApfV4GeneratorBase<?> emitPrologueLocked() throws IllegalInstructionException { // This is guaranteed to succeed because of the check in maybeCreate. ApfV4GeneratorBase<?> gen; if (shouldUseApfV6Generator()) { @@ -2559,7 +2569,7 @@ private synchronized void collectAndSendMetrics() { if (mIpClientRaInfoMetrics == null || mApfSessionInfoMetrics == null) return; - final long sessionDurationMs = mClock.elapsedRealtime() - mSessionStartMs; + final long sessionDurationMs = mDependencies.elapsedRealtime() - mSessionStartMs; if (sessionDurationMs < mMinMetricsSessionDurationMs) return; // Collect and send IpClientRaInfoMetrics.
diff --git a/tests/unit/src/android/net/apf/ApfFilterTest.kt b/tests/unit/src/android/net/apf/ApfFilterTest.kt index d9bc6ab..938bf25 100644 --- a/tests/unit/src/android/net/apf/ApfFilterTest.kt +++ b/tests/unit/src/android/net/apf/ApfFilterTest.kt
@@ -39,6 +39,7 @@ import android.net.apf.BaseApfGenerator.APF_VERSION_6 import android.net.ip.IpClient.IpClientCallbacksWrapper import android.os.Build +import android.os.SystemClock import android.system.OsConstants.IFA_F_TENTATIVE import androidx.test.filters.SmallTest import com.android.internal.annotations.GuardedBy @@ -171,6 +172,7 @@ mApfFilterCreated.add(invocation.getArgument(0)) } }.`when`(dependencies).onApfFilterCreated(any()) + `when`(dependencies.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime()) } private fun shutdownApfFilters() {
diff --git a/tests/unit/src/android/net/apf/ApfTest.java b/tests/unit/src/android/net/apf/ApfTest.java index 9c36df7..c80aaa9 100644 --- a/tests/unit/src/android/net/apf/ApfTest.java +++ b/tests/unit/src/android/net/apf/ApfTest.java
@@ -17,6 +17,7 @@ package android.net.apf; import static android.net.apf.ApfCounterTracker.Counter.getCounterEnumFromOffset; +import static android.net.apf.ApfTestHelpers.consumeInstalledProgram; import static android.net.apf.BaseApfGenerator.APF_VERSION_3; import static android.net.apf.BaseApfGenerator.APF_VERSION_4; import static android.net.apf.BaseApfGenerator.APF_VERSION_6; @@ -34,6 +35,7 @@ import static android.net.apf.ApfTestUtils.assertProgramEquals; import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED; import static android.os.PowerManager.ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED; +import static android.system.OsConstants.AF_UNIX; import static android.system.OsConstants.ETH_P_ARP; import static android.system.OsConstants.ETH_P_IP; import static android.system.OsConstants.ETH_P_IPV6; @@ -41,6 +43,7 @@ import static android.system.OsConstants.IPPROTO_IPV6; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; +import static android.system.OsConstants.SOCK_STREAM; import static com.android.net.module.util.HexDump.hexStringToByteArray; import static com.android.net.module.util.HexDump.toHexString; @@ -49,14 +52,17 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.content.BroadcastReceiver; import android.content.Context; @@ -70,14 +76,15 @@ import android.net.TcpKeepalivePacketDataParcelable; import android.net.apf.ApfCounterTracker.Counter; import android.net.apf.ApfFilter.ApfConfiguration; -import android.net.apf.ApfTestUtils.MockIpClientCallback; -import android.net.apf.ApfTestUtils.TestApfFilter; import android.net.apf.BaseApfGenerator.IllegalInstructionException; +import android.net.ip.IpClient; import android.net.metrics.IpConnectivityLog; import android.os.Build; import android.os.PowerManager; +import android.os.SystemClock; import android.stats.connectivity.NetworkQuirkEvent; import android.system.ErrnoException; +import android.system.Os; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArrayMap; @@ -92,6 +99,7 @@ import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.DnsPacket; import com.android.net.module.util.Inet4AddressUtils; +import com.android.net.module.util.InterfaceParams; import com.android.net.module.util.NetworkStackConstants; import com.android.net.module.util.PacketBuilder; import com.android.networkstack.metrics.ApfSessionInfoMetrics; @@ -102,6 +110,7 @@ import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRunner; +import libcore.io.IoUtils; import libcore.io.Streams; import org.junit.After; @@ -117,6 +126,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -165,12 +175,15 @@ @Mock private NetworkQuirkMetrics mNetworkQuirkMetrics; @Mock private ApfSessionInfoMetrics mApfSessionInfoMetrics; @Mock private IpClientRaInfoMetrics mIpClientRaInfoMetrics; - @Mock private ApfFilter.Clock mClock; + @Mock private IpClient.IpClientCallbacksWrapper mIpClientCb; @GuardedBy("mApfFilterCreated") private final ArrayList<AndroidPacketFilter> mApfFilterCreated = new ArrayList<>(); @GuardedBy("mThreadsToBeCleared") private final ArrayList<Thread> mThreadsToBeCleared = new ArrayList<>(); + private FileDescriptor mWriteSocket; + private long mCurrentTimeMs; + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -189,13 +202,20 @@ } return null; }).when(mDependencies).onThreadCreated(any()); + FileDescriptor readSocket = new FileDescriptor(); + mWriteSocket = new FileDescriptor(); + Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket); + doReturn(readSocket).when(mDependencies).createRaReaderSocket(anyInt()); + mCurrentTimeMs = SystemClock.elapsedRealtime(); + doReturn(mCurrentTimeMs).when(mDependencies).elapsedRealtime(); + doReturn(true).when(mIpClientCb).installPacketFilter(any()); } private void quitThreads() throws Exception { ConcurrentUtils.quitThreads( THREAD_QUIT_MAX_RETRY_COUNT, false /* interrupt */, - HANDLER_TIMEOUT_MS, + TIMEOUT_MS, () -> { synchronized (mThreadsToBeCleared) { final ArrayList<Thread> ret = new ArrayList<>(mThreadsToBeCleared); @@ -231,6 +251,8 @@ shutdownApfFilters(); // Clear mocks to prevent from stubs holding instances and cause memory leaks. Mockito.framework().clearInlineMocks(); + IoUtils.closeQuietly(mWriteSocket); + mWriteSocket = null; } private static final String TAG = "ApfTest"; @@ -245,7 +267,8 @@ private static final int MIN_RDNSS_LIFETIME_SEC = 0; private static final int MIN_METRICS_SESSION_DURATIONS_MS = 300_000; - private static final int HANDLER_TIMEOUT_MS = 1000; + private static final int TIMEOUT_MS = 1000; + private static final int NO_CALLBACK_TIMEOUT_MS = 500; private static final int THREAD_QUIT_MAX_RETRY_COUNT = 3; // Constants for opcode encoding @@ -258,6 +281,11 @@ private static final byte SIZE32 = (byte)(3 << 1); private static final byte R1_REG = 1; + private static final byte[] TEST_MAC_ADDR = {2, 3, 4, 5, 6, 7}; + private static final int TEST_IFACE_IDX = 1234; + private static final InterfaceParams TEST_PARAMS = new InterfaceParams("lo", TEST_IFACE_IDX, + MacAddress.fromBytes(TEST_MAC_ADDR), 1500 /* defaultMtu */); + private static ApfConfiguration getDefaultConfig() { ApfFilter.ApfConfiguration config = new ApfConfiguration(); config.apfVersionSupported = 2; @@ -1006,6 +1034,11 @@ } } + private void pretendPacketReceived(byte[] packet) + throws IOException, ErrnoException { + Os.write(mWriteSocket, packet, 0, packet.length); + } + /** * Generate APF program, run pcap file though APF filter, then check all the packets in the file * should be dropped. @@ -1014,7 +1047,6 @@ public void testApfFilterPcapFile() throws Exception { final byte[] MOCK_PCAP_IPV4_ADDR = {(byte) 172, 16, 7, (byte) 151}; String pcapFilename = stageFile(R.raw.apfPcap); - MockIpClientCallback ipClientCallback = new MockIpClientCallback(); LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_PCAP_IPV4_ADDR), 16); LinkProperties lp = new LinkProperties(); lp.addLinkAddress(link); @@ -1024,10 +1056,11 @@ config.apfRamSize = 1700; config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, - mNetworkQuirkMetrics, mDependencies); + ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, + mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 2 /* installCnt */); apfFilter.setLinkProperties(lp); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); byte[] data = new byte[Counter.totalSize()]; final boolean result; @@ -1193,18 +1226,18 @@ @Test public void testApfFilterIPv4() throws Exception { - MockIpClientCallback ipClientCallback = new MockIpClientCallback(); LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); LinkProperties lp = new LinkProperties(); lp.addLinkAddress(link); ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; - TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, - mNetworkQuirkMetrics, mDependencies); + ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, + mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); apfFilter.setLinkProperties(lp); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); ByteBuffer packet = ByteBuffer.wrap(new byte[100]); if (SdkLevel.isAtLeastV()) { @@ -1216,7 +1249,7 @@ } // Verify unicast IPv4 packet is passed - put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR); + put(packet, ETH_DEST_ADDR_OFFSET, TEST_MAC_ADDR); packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR); assertPass(program, packet.array()); @@ -1244,21 +1277,20 @@ assertDrop(program, packet.array()); // Verify broadcast IPv4 DHCP to us is passed - put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR); + put(packet, DHCP_CLIENT_MAC_OFFSET, TEST_MAC_ADDR); assertPass(program, packet.array()); // Verify unicast IPv4 DHCP to us is passed - put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR); + put(packet, ETH_DEST_ADDR_OFFSET, TEST_MAC_ADDR); assertPass(program, packet.array()); } @Test public void testApfFilterIPv6() throws Exception { - MockIpClientCallback ipClientCallback = new MockIpClientCallback(); ApfConfiguration config = getDefaultConfig(); - TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Verify empty IPv6 packet is passed ByteBuffer packet = makeIpv6Packet(IPPROTO_UDP); @@ -1664,18 +1696,18 @@ final byte[] multicastIpv4Addr = {(byte)224,0,0,1}; final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb}; - MockIpClientCallback ipClientCallback = new MockIpClientCallback(); LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24); LinkProperties lp = new LinkProperties(); lp.addLinkAddress(link); ApfConfiguration config = getDefaultConfig(); config.ieee802_3Filter = DROP_802_3_FRAMES; - TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); apfFilter.setLinkProperties(lp); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Construct IPv4 and IPv6 multicast packets. ByteBuffer mcastv4packet = makeIpv4Packet(IPPROTO_UDP); @@ -1697,7 +1729,7 @@ // Construct IPv4 broadcast with L2 unicast address packet (b/30231088). ByteBuffer bcastv4unicastl2packet = makeIpv4Packet(IPPROTO_UDP); - bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR); + bcastv4unicastl2packet.put(TEST_MAC_ADDR); bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr); @@ -1709,9 +1741,8 @@ assertPass(program, bcastv4unicastl2packet.array()); // Turn on multicast filter and verify it works - ipClientCallback.resetApfProgramWait(); apfFilter.setMulticastFilter(true); - program = ipClientCallback.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); assertDrop(program, mcastv4packet.array()); assertDrop(program, mcastv6packet.array()); assertDrop(program, bcastv4packet1.array()); @@ -1719,9 +1750,8 @@ assertDrop(program, bcastv4unicastl2packet.array()); // Turn off multicast filter and verify it's off - ipClientCallback.resetApfProgramWait(); apfFilter.setMulticastFilter(false); - program = ipClientCallback.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); assertPass(program, mcastv4packet.array()); assertPass(program, mcastv6packet.array()); assertPass(program, bcastv4packet1.array()); @@ -1729,13 +1759,14 @@ assertPass(program, bcastv4unicastl2packet.array()); // Verify it can be initialized to on - ipClientCallback.resetApfProgramWait(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mNetworkQuirkMetrics, - mDependencies); + clearInvocations(mIpClientCb); + apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, + mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); apfFilter.setLinkProperties(lp); - program = ipClientCallback.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); assertDrop(program, mcastv4packet.array()); assertDrop(program, mcastv6packet.array()); assertDrop(program, bcastv4packet1.array()); @@ -1758,10 +1789,10 @@ } private void doTestApfFilterMulticastPingWhileDozing(boolean isLightDozing) throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); final ApfConfiguration configuration = getDefaultConfig(); - final ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, - configuration, mNetworkQuirkMetrics, mDependencies); + final ApfFilter apfFilter = new ApfFilter(mContext, configuration, TEST_PARAMS, + mIpClientCb, mNetworkQuirkMetrics, mDependencies); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); final ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); verify(mDependencies).addDeviceIdleReceiver(receiverCaptor.capture()); @@ -1774,7 +1805,7 @@ put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr); // Normally, we let multicast pings alone... - assertPass(ipClientCallback.assertProgramUpdateAndGet(), packet.array()); + assertPass(program, packet.array()); if (isLightDozing) { doReturn(true).when(mPowerManager).isDeviceLightIdleMode(); @@ -1783,19 +1814,21 @@ doReturn(true).when(mPowerManager).isDeviceIdleMode(); receiver.onReceive(mContext, new Intent(ACTION_DEVICE_IDLE_MODE_CHANGED)); } + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // ...and even while dozing... - assertPass(ipClientCallback.assertProgramUpdateAndGet(), packet.array()); + assertPass(program, packet.array()); // ...but when the multicast filter is also enabled, drop the multicast pings to save power. apfFilter.setMulticastFilter(true); - assertDrop(ipClientCallback.assertProgramUpdateAndGet(), packet.array()); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); + assertDrop(program, packet.array()); // However, we should still let through all other ICMPv6 types. ByteBuffer raPacket = ByteBuffer.wrap(packet.array().clone()); setIpv6VersionFields(packet); packet.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_ICMPV6); raPacket.put(ICMP6_TYPE_OFFSET, (byte) NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT); - assertPass(ipClientCallback.assertProgramUpdateAndGet(), raPacket.array()); + assertPass(program, raPacket.array()); // Now wake up from doze mode to ensure that we no longer drop the packets. // (The multicast filter is still enabled at this point). @@ -1806,17 +1839,17 @@ doReturn(false).when(mPowerManager).isDeviceIdleMode(); receiver.onReceive(mContext, new Intent(ACTION_DEVICE_IDLE_MODE_CHANGED)); } - assertPass(ipClientCallback.assertProgramUpdateAndGet(), packet.array()); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); + assertPass(program, packet.array()); } @Test @DevSdkIgnoreRule.IgnoreAfter(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) public void testApfFilter802_3() throws Exception { - MockIpClientCallback ipClientCallback = new MockIpClientCallback(); ApfConfiguration config = getDefaultConfig(); - ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config, + ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Verify empty packet of 100 zero bytes is passed // Note that eth-type = 0 makes it an IEEE802.3 frame @@ -1832,11 +1865,10 @@ assertPass(program, packet.array()); // Now turn on the filter - ipClientCallback.resetApfProgramWait(); config.ieee802_3Filter = DROP_802_3_FRAMES; - apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config, + apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); - program = ipClientCallback.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Verify that IEEE802.3 frame is dropped // In this case ethtype is used for payload length @@ -1859,11 +1891,10 @@ final int[] ipv4BlackList = {ETH_P_IP}; final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6}; - MockIpClientCallback ipClientCallback = new MockIpClientCallback(); ApfConfiguration config = getDefaultConfig(); - ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config, + ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Verify empty packet of 100 zero bytes is passed // Note that eth-type = 0 makes it an IEEE802.3 frame @@ -1879,11 +1910,10 @@ assertPass(program, packet.array()); // Now add IPv4 to the black list - ipClientCallback.resetApfProgramWait(); config.ethTypeBlackList = ipv4BlackList; - apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config, + apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); - program = ipClientCallback.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Verify that IPv4 frame will be dropped setIpv4VersionFields(packet); @@ -1894,11 +1924,10 @@ assertPass(program, packet.array()); // Now let us have both IPv4 and IPv6 in the black list - ipClientCallback.resetApfProgramWait(); config.ethTypeBlackList = ipv4Ipv6BlackList; - apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config, + apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); - program = ipClientCallback.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Verify that IPv4 frame will be dropped setIpv4VersionFields(packet); @@ -1909,12 +1938,6 @@ assertDrop(program, packet.array()); } - private byte[] getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp) { - cb.resetApfProgramWait(); - filter.setLinkProperties(lp); - return cb.assertProgramUpdateAndGet(); - } - private void verifyArpFilter(byte[] program, int filterResult) { // Verify ARP request packet assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR)); @@ -1938,24 +1961,28 @@ @Test public void testApfFilterArp() throws Exception { - MockIpClientCallback ipClientCallback = new MockIpClientCallback(); ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Verify initially ARP request filter is off, and GARP filter is on. - verifyArpFilter(ipClientCallback.assertProgramUpdateAndGet(), PASS); + verifyArpFilter(program, PASS); // Inform ApfFilter of our address and verify ARP filtering is on LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24); LinkProperties lp = new LinkProperties(); assertTrue(lp.addLinkAddress(linkAddress)); - verifyArpFilter(getProgram(ipClientCallback, apfFilter, lp), DROP); + apfFilter.setLinkProperties(lp); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); + verifyArpFilter(program, DROP); + apfFilter.setLinkProperties(new LinkProperties()); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Inform ApfFilter of loss of IP and verify ARP filtering is off - verifyArpFilter(getProgram(ipClientCallback, apfFilter, new LinkProperties()), PASS); + verifyArpFilter(program, PASS); } private static byte[] arpReply(byte[] sip, byte[] tip) { @@ -1997,12 +2024,12 @@ @Test public void testApfFilterKeepaliveAck() throws Exception { - final MockIpClientCallback cb = new MockIpClientCallback(); final ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - final TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); byte[] program; final int srcPort = 12345; final int dstPort = 54321; @@ -2031,7 +2058,7 @@ parcel.ack = ackNum; apfFilter.addTcpKeepalivePacketFilter(slot1, parcel); - program = cb.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Verify IPv4 keepalive ack packet is dropped // src: 10.0.0.6, port: 54321 @@ -2053,6 +2080,7 @@ // Remove IPv4 keepalive filter apfFilter.removeKeepalivePacketFilter(slot1); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); try { // src: 2404:0:0:0:0:0:faf1, port: 12345 @@ -2070,7 +2098,7 @@ ipv6Parcel.ack = ackNum; apfFilter.addTcpKeepalivePacketFilter(slot1, ipv6Parcel); - program = cb.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Verify IPv6 keepalive ack packet is dropped // src: 2404:0:0:0:0:0:faf2, port: 54321 @@ -2093,7 +2121,7 @@ // Verify multiple filters apfFilter.addTcpKeepalivePacketFilter(slot1, parcel); apfFilter.addTcpKeepalivePacketFilter(slot2, ipv6Parcel); - program = cb.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 3 /* installCnt */); // Verify IPv4 keepalive ack packet is dropped // src: 10.0.0.6, port: 54321 @@ -2132,8 +2160,6 @@ // TODO: support V6 packets } - program = cb.assertProgramUpdateAndGet(); - // Verify IPv4, IPv6 packets are passed assertPass(program, ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR, @@ -2189,12 +2215,12 @@ @Test public void testApfFilterNattKeepalivePacket() throws Exception { - final MockIpClientCallback cb = new MockIpClientCallback(); final ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - final TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); byte[] program; final int srcPort = 1024; final int dstPort = 4500; @@ -2215,7 +2241,7 @@ parcel.dstPort = dstPort; apfFilter.addNattKeepalivePacketFilter(slot1, parcel); - program = cb.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Verify IPv4 keepalive packet is dropped // src: 10.0.0.6, port: 4500 @@ -2440,10 +2466,9 @@ @Test public void testRaToString() throws Exception { - MockIpClientCallback cb = new MockIpClientCallback(); ApfConfiguration config = getDefaultConfig(); - TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mNetworkQuirkMetrics, - mDependencies); + ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, + mNetworkQuirkMetrics, mDependencies); byte[] packet = buildLargeRa(); ApfFilter.Ra ra = apfFilter.new Ra(packet, packet.length); @@ -2493,29 +2518,32 @@ // Test that when ApfFilter is shown the given packet, it generates a program to filter it // for the given lifetime. - private void verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, - ByteBuffer packet, int lifetime) throws IOException, ErrnoException { + private byte[] verifyRaLifetime(ByteBuffer packet, int lifetime) + throws IOException, ErrnoException { // Verify new program generated if ApfFilter witnesses RA - apfFilter.pretendPacketReceived(packet.array()); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + clearInvocations(mIpClientCb); + pretendPacketReceived(packet.array()); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); verifyRaLifetime(program, packet, lifetime); + return program; } - private void assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, - ByteBuffer packet) throws IOException, ErrnoException { - apfFilter.pretendPacketReceived(packet.array()); - ipClientCallback.assertNoProgramUpdate(); + private void assertInvalidRa(ByteBuffer packet) + throws IOException, ErrnoException, InterruptedException { + clearInvocations(mIpClientCb); + pretendPacketReceived(packet.array()); + Thread.sleep(NO_CALLBACK_TIMEOUT_MS); + verify(mIpClientCb, never()).installPacketFilter(any()); } @Test public void testApfFilterRa() throws Exception { - MockIpClientCallback ipClientCallback = new MockIpClientCallback(); ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); final int ROUTER_LIFETIME = 1000; final int PREFIX_VALID_LIFETIME = 200; @@ -2530,7 +2558,7 @@ ByteBuffer basePacket = ByteBuffer.wrap(ra.build()); assertPass(program, basePacket.array()); - verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME); + verifyRaLifetime(basePacket, ROUTER_LIFETIME); ra = new RaPacketBuilder(ROUTER_LIFETIME); // Check that changes are ignored in every byte of the flow label. @@ -2542,7 +2570,7 @@ ra = new RaPacketBuilder(ROUTER_LIFETIME); ra.addZeroLengthOption(); ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(ra.build()); - assertInvalidRa(apfFilter, ipClientCallback, zeroLengthOptionPacket); + assertInvalidRa(zeroLengthOptionPacket); // Generate several RAs with different options and lifetimes, and verify when // ApfFilter is shown these packets, it generates programs to filter them for the @@ -2550,43 +2578,39 @@ ra = new RaPacketBuilder(ROUTER_LIFETIME); ra.addPioOption(PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, "2001:db8::/64"); ByteBuffer prefixOptionPacket = ByteBuffer.wrap(ra.build()); - verifyRaLifetime( - apfFilter, ipClientCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME); + verifyRaLifetime(prefixOptionPacket, PREFIX_PREFERRED_LIFETIME); ra = new RaPacketBuilder(ROUTER_LIFETIME); ra.addRdnssOption(RDNSS_LIFETIME, "2001:4860:4860::8888", "2001:4860:4860::8844"); ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(ra.build()); - verifyRaLifetime(apfFilter, ipClientCallback, rdnssOptionPacket, RDNSS_LIFETIME); + verifyRaLifetime(rdnssOptionPacket, RDNSS_LIFETIME); final int lowLifetime = 60; ra = new RaPacketBuilder(ROUTER_LIFETIME); ra.addRdnssOption(lowLifetime, "2620:fe::9"); ByteBuffer lowLifetimeRdnssOptionPacket = ByteBuffer.wrap(ra.build()); - verifyRaLifetime(apfFilter, ipClientCallback, lowLifetimeRdnssOptionPacket, - ROUTER_LIFETIME); + verifyRaLifetime(lowLifetimeRdnssOptionPacket, ROUTER_LIFETIME); ra = new RaPacketBuilder(ROUTER_LIFETIME); ra.addRioOption(ROUTE_LIFETIME, "64:ff9b::/96"); ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(ra.build()); - verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME); + program = verifyRaLifetime(routeInfoOptionPacket, ROUTE_LIFETIME); // Check that RIOs differing only in the first 4 bytes are different. ra = new RaPacketBuilder(ROUTER_LIFETIME); ra.addRioOption(ROUTE_LIFETIME, "64:ff9b::/64"); // Packet should be passed because it is different. - program = ipClientCallback.assertProgramUpdateAndGet(); assertPass(program, ra.build()); ra = new RaPacketBuilder(ROUTER_LIFETIME); ra.addDnsslOption(DNSSL_LIFETIME, "test.example.com", "one.more.example.com"); ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(ra.build()); - verifyRaLifetime(apfFilter, ipClientCallback, dnsslOptionPacket, ROUTER_LIFETIME); + verifyRaLifetime(dnsslOptionPacket, ROUTER_LIFETIME); ByteBuffer largeRaPacket = ByteBuffer.wrap(buildLargeRa()); - verifyRaLifetime(apfFilter, ipClientCallback, largeRaPacket, 300); + program = verifyRaLifetime(largeRaPacket, 300); // Verify that current program filters all the RAs (note: ApfFilter.MAX_RAS == 10). - program = ipClientCallback.assertProgramUpdateAndGet(); verifyRaLifetime(program, basePacket, ROUTER_LIFETIME); verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME); verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME); @@ -2599,13 +2623,12 @@ @Test public void testRaWithDifferentReachableTimeAndRetransTimer() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); final ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); final int RA_REACHABLE_TIME = 1800; final int RA_RETRANSMISSION_TIMER = 1234; @@ -2619,8 +2642,8 @@ assertPass(program, raPacket); // Assume apf is shown the given RA, it generates program to filter it. - apfFilter.pretendPacketReceived(raPacket); - program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(raPacket); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); assertDrop(program, raPacket); // A packet with different reachable time should be passed. @@ -2641,13 +2664,12 @@ @SuppressWarnings("ByteBufferBackingArray") @Test public void testRaWithProgramInstalledSomeTimeAfterLastSeen() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); final ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); final int routerLifetime = 1000; final int timePassedSeconds = 12; @@ -2655,26 +2677,32 @@ // Verify that when the program is generated and installed some time after RA is last seen // it should be installed with the correct remaining lifetime. ByteBuffer basePacket = ByteBuffer.wrap(new RaPacketBuilder(routerLifetime).build()); - verifyRaLifetime(apfFilter, ipClientCallback, basePacket, routerLifetime); - apfFilter.increaseCurrentTimeSeconds(timePassedSeconds); + verifyRaLifetime(basePacket, routerLifetime); + + mCurrentTimeMs += timePassedSeconds * DateUtils.SECOND_IN_MILLIS; + doReturn(mCurrentTimeMs).when(mDependencies).elapsedRealtime(); synchronized (apfFilter) { apfFilter.installNewProgramLocked(); } - program = ipClientCallback.assertProgramUpdateAndGet(); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); verifyRaLifetime(program, basePacket, routerLifetime, timePassedSeconds); // Packet should be passed if the program is installed after 1/6 * lifetime from last seen - apfFilter.increaseCurrentTimeSeconds((int) (routerLifetime / 6) - timePassedSeconds - 1); + mCurrentTimeMs += + ((routerLifetime / 6) - timePassedSeconds - 1) * DateUtils.SECOND_IN_MILLIS; + doReturn(mCurrentTimeMs).when(mDependencies).elapsedRealtime(); synchronized (apfFilter) { apfFilter.installNewProgramLocked(); } - program = ipClientCallback.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); assertDrop(program, basePacket.array()); - apfFilter.increaseCurrentTimeSeconds(1); + + mCurrentTimeMs += DateUtils.SECOND_IN_MILLIS; + doReturn(mCurrentTimeMs).when(mDependencies).elapsedRealtime(); synchronized (apfFilter) { apfFilter.installNewProgramLocked(); } - program = ipClientCallback.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); assertPass(program, basePacket.array()); } @@ -2709,12 +2737,11 @@ public void testRaParsing() throws Exception { final int maxRandomPacketSize = 512; final Random r = new Random(); - MockIpClientCallback cb = new MockIpClientCallback(); ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mNetworkQuirkMetrics, - mDependencies); + ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, + mNetworkQuirkMetrics, mDependencies); for (int i = 0; i < 1000; i++) { byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; r.nextBytes(packet); @@ -2731,12 +2758,11 @@ public void testRaProcessing() throws Exception { final int maxRandomPacketSize = 512; final Random r = new Random(); - MockIpClientCallback cb = new MockIpClientCallback(); ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mNetworkQuirkMetrics, - mDependencies); + ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, + mNetworkQuirkMetrics, mDependencies); for (int i = 0; i < 1000; i++) { byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; r.nextBytes(packet); @@ -2750,34 +2776,34 @@ @Test public void testMatchedRaUpdatesLifetime() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); - final TestApfFilter apfFilter = new TestApfFilter(mContext, getDefaultConfig(), - ipClientCallback, mNetworkQuirkMetrics, mDependencies); + final ApfFilter apfFilter = new ApfFilter(mContext, getDefaultConfig(), TEST_PARAMS, + mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Create an RA and build an APF program byte[] ra = new RaPacketBuilder(1800 /* router lifetime */).build(); - apfFilter.pretendPacketReceived(ra); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // lifetime dropped significantly, assert pass ra = new RaPacketBuilder(200 /* router lifetime */).build(); assertPass(program, ra); // update program with the new RA - apfFilter.pretendPacketReceived(ra); - program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // assert program was updated and new lifetimes were taken into account. assertDrop(program, ra); } - @Test public void testProcessRaWithInfiniteLifeTimeWithoutCrash() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); // configure accept_ra_min_lft final ApfConfiguration config = getDefaultConfig(); config.acceptRaMinLft = 180; - TestApfFilter apfFilter; + ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, + mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Template packet: // Frame 1: 150 bytes on wire (1200 bits), 150 bytes captured (1200 bits) // Ethernet II, Src: Netgear_23:67:2c (28:c6:8e:23:67:2c), Dst: IPv6mcast_01 (33:33:00:00:00:01) @@ -2825,13 +2851,11 @@ final String packetStringFmt = "33330000000128C68E23672C86DD60054C6B00603AFFFE800000000000002AC68EFFFE23672CFF02000000000000000000000000000186000ACD40C01B580000000000000000010128C68E23672C05010000000005DC030440C0%s000000002401FA000480F00000000000000000001903000000001B582401FA000480F000000000000000000107010000000927C0"; final List<String> lifetimes = List.of("FFFFFFFF", "00000000", "00000001", "00001B58"); for (String lifetime : lifetimes) { - apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mNetworkQuirkMetrics, - mDependencies); final byte[] ra = hexStringToByteArray( String.format(packetStringFmt, lifetime + lifetime)); // feed the RA into APF and generate the filter, the filter shouldn't crash. - apfFilter.pretendPacketReceived(ra); - ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); } } @@ -2839,20 +2863,20 @@ // Old lifetime is 0 @Test public void testAcceptRaMinLftCase1a() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); // configure accept_ra_min_lft final ApfConfiguration config = getDefaultConfig(); config.acceptRaMinLft = 180; - final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Create an initial RA and build an APF program byte[] ra = new RaPacketBuilder(1800 /* router lifetime */) .addPioOption(1800 /*valid*/, 0 /*preferred*/, "2001:db8::/64") .build(); - apfFilter.pretendPacketReceived(ra); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // repeated RA is dropped assertDrop(program, ra); @@ -2868,20 +2892,20 @@ // Old lifetime is > 0 @Test public void testAcceptRaMinLftCase2a() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); // configure accept_ra_min_lft final ApfConfiguration config = getDefaultConfig(); config.acceptRaMinLft = 180; - final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Create an initial RA and build an APF program byte[] ra = new RaPacketBuilder(1800 /* router lifetime */) .addPioOption(1800 /*valid*/, 100 /*preferred*/, "2001:db8::/64") .build(); - apfFilter.pretendPacketReceived(ra); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // repeated RA is dropped assertDrop(program, ra); @@ -2904,18 +2928,18 @@ // Old lifetime is 0 @Test public void testAcceptRaMinLftCase1b() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); // configure accept_ra_min_lft final ApfConfiguration config = getDefaultConfig(); config.acceptRaMinLft = 180; - final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Create an initial RA and build an APF program byte[] ra = new RaPacketBuilder(0 /* router lifetime */).build(); - apfFilter.pretendPacketReceived(ra); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // repeated RA is dropped assertDrop(program, ra); @@ -2929,23 +2953,22 @@ assertPass(program, ra); } - // Test for go/apf-ra-filter Case 2b. // Old lifetime is < accept_ra_min_lft (but not 0). @Test public void testAcceptRaMinLftCase2b() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); // configure accept_ra_min_lft final ApfConfiguration config = getDefaultConfig(); config.acceptRaMinLft = 180; - final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Create an initial RA and build an APF program byte[] ra = new RaPacketBuilder(100 /* router lifetime */).build(); - apfFilter.pretendPacketReceived(ra); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // repeated RA is dropped assertDrop(program, ra); @@ -2971,18 +2994,18 @@ // Old lifetime is >= accept_ra_min_lft and <= 3 * accept_ra_min_lft @Test public void testAcceptRaMinLftCase3b() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); // configure accept_ra_min_lft final ApfConfiguration config = getDefaultConfig(); config.acceptRaMinLft = 180; - final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Create an initial RA and build an APF program byte[] ra = new RaPacketBuilder(200 /* router lifetime */).build(); - apfFilter.pretendPacketReceived(ra); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // repeated RA is dropped assertDrop(program, ra); @@ -3004,18 +3027,18 @@ // Old lifetime is > 3 * accept_ra_min_lft @Test public void testAcceptRaMinLftCase4b() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); // configure accept_ra_min_lft final ApfConfiguration config = getDefaultConfig(); config.acceptRaMinLft = 180; - final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Create an initial RA and build an APF program byte[] ra = new RaPacketBuilder(1800 /* router lifetime */).build(); - apfFilter.pretendPacketReceived(ra); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // repeated RA is dropped assertDrop(program, ra); @@ -3043,17 +3066,17 @@ @Test public void testRaFilterIsUpdated() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); // configure accept_ra_min_lft final ApfConfiguration config = getDefaultConfig(); config.acceptRaMinLft = 180; - final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Create an initial RA and build an APF program byte[] ra = new RaPacketBuilder(1800 /* router lifetime */).build(); - apfFilter.pretendPacketReceived(ra); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + byte[] program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // repeated RA is dropped. assertDrop(program, ra); @@ -3061,38 +3084,38 @@ // updated RA is passed, repeated RA is dropped after program update. ra = new RaPacketBuilder(599 /* router lifetime */).build(); assertPass(program, ra); - apfFilter.pretendPacketReceived(ra); - program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); assertDrop(program, ra); ra = new RaPacketBuilder(180 /* router lifetime */).build(); assertPass(program, ra); - apfFilter.pretendPacketReceived(ra); - program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); assertDrop(program, ra); ra = new RaPacketBuilder(0 /* router lifetime */).build(); assertPass(program, ra); - apfFilter.pretendPacketReceived(ra); - program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); assertDrop(program, ra); ra = new RaPacketBuilder(180 /* router lifetime */).build(); assertPass(program, ra); - apfFilter.pretendPacketReceived(ra); - program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); assertDrop(program, ra); ra = new RaPacketBuilder(599 /* router lifetime */).build(); assertPass(program, ra); - apfFilter.pretendPacketReceived(ra); - program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); assertDrop(program, ra); ra = new RaPacketBuilder(1800 /* router lifetime */).build(); assertPass(program, ra); - apfFilter.pretendPacketReceived(ra); - program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); assertDrop(program, ra); } @@ -3115,18 +3138,12 @@ assertEquals(want, got); } - private TestAndroidPacketFilter makeTestApfFilter(ApfConfiguration config, - MockIpClientCallback ipClientCallback) throws Exception { - return new TestApfFilter(mContext, config, ipClientCallback, mNetworkQuirkMetrics, - mDependencies, mClock); - } - - @Test public void testInstallPacketFilterFailure() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(false); + doReturn(false).when(mIpClientCb).installPacketFilter(any()); final ApfConfiguration config = getDefaultConfig(); - final TestAndroidPacketFilter apfFilter = makeTestApfFilter(config, ipClientCallback); + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, + mNetworkQuirkMetrics, mDependencies); verify(mNetworkQuirkMetrics).setEvent(NetworkQuirkEvent.QE_APF_INSTALL_FAILURE); verify(mNetworkQuirkMetrics).statsWrite(); reset(mNetworkQuirkMetrics); @@ -3140,28 +3157,27 @@ @Test public void testApfProgramOverSize() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); final ApfConfiguration config = getDefaultConfig(); config.apfVersionSupported = 2; config.apfRamSize = 512; - final TestAndroidPacketFilter apfFilter = makeTestApfFilter(config, ipClientCallback); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, + mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); final byte[] ra = buildLargeRa(); - apfFilter.pretendPacketReceived(ra); + pretendPacketReceived(ra); // The generated program size will be 529, which is larger than 512 - program = ipClientCallback.assertProgramUpdateAndGet(); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); verify(mNetworkQuirkMetrics).setEvent(NetworkQuirkEvent.QE_APF_OVER_SIZE_FAILURE); verify(mNetworkQuirkMetrics).statsWrite(); } @Test public void testGenerateApfProgramException() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); final ApfConfiguration config = getDefaultConfig(); - final TestAndroidPacketFilter apfFilter; - apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mNetworkQuirkMetrics, - mDependencies, true /* throwsExceptionWhenGeneratesProgram */); + ApfFilter apfFilter = spy(new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, + mNetworkQuirkMetrics, mDependencies)); synchronized (apfFilter) { + when(apfFilter.emitPrologueLocked()).thenThrow(new IllegalStateException("test")); apfFilter.installNewProgramLocked(); } verify(mNetworkQuirkMetrics).setEvent(NetworkQuirkEvent.QE_APF_GENERATE_FILTER_EXCEPTION); @@ -3170,17 +3186,17 @@ @Test public void testApfSessionInfoMetrics() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); final ApfConfiguration config = getDefaultConfig(); config.apfVersionSupported = 4; config.apfRamSize = 4096; final long startTimeMs = 12345; final long durationTimeMs = config.minMetricsSessionDurationMs; - doReturn(startTimeMs).when(mClock).elapsedRealtime(); - final TestAndroidPacketFilter apfFilter = makeTestApfFilter(config, ipClientCallback); + doReturn(startTimeMs).when(mDependencies).elapsedRealtime(); + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, + mNetworkQuirkMetrics, mDependencies); + byte[] program = consumeInstalledProgram(mIpClientCb, 2 /* installCnt */); int maxProgramSize = 0; int numProgramUpdated = 0; - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); maxProgramSize = Math.max(maxProgramSize, program.length); numProgramUpdated++; @@ -3197,14 +3213,14 @@ expectedData[totalPacketsCounterIdx + 3] += 1; expectedData[passedIpv6IcmpCounterIdx + 3] += 1; assertDataMemoryContentsIgnoreVersion(PASS, program, ra, data, expectedData); - apfFilter.pretendPacketReceived(ra); - program = ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); maxProgramSize = Math.max(maxProgramSize, program.length); numProgramUpdated++; apfFilter.setMulticastFilter(true); // setMulticastFilter will trigger program installation. - program = ipClientCallback.assertProgramUpdateAndGet(); + program = consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); maxProgramSize = Math.max(maxProgramSize, program.length); numProgramUpdated++; @@ -3221,7 +3237,7 @@ apfFilter.setDataSnapshot(data); // Write metrics data to statsd pipeline when shutdown. - doReturn(startTimeMs + durationTimeMs).when(mClock).elapsedRealtime(); + doReturn(startTimeMs + durationTimeMs).when(mDependencies).elapsedRealtime(); apfFilter.shutdown(); verify(mApfSessionInfoMetrics).setVersion(4); verify(mApfSessionInfoMetrics).setMemorySize(4096); @@ -3250,13 +3266,13 @@ @Test public void testIpClientRaInfoMetrics() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); final ApfConfiguration config = getDefaultConfig(); final long startTimeMs = 12345; final long durationTimeMs = config.minMetricsSessionDurationMs; - doReturn(startTimeMs).when(mClock).elapsedRealtime(); - final TestAndroidPacketFilter apfFilter = makeTestApfFilter(config, ipClientCallback); - byte[] program = ipClientCallback.assertProgramUpdateAndGet(); + doReturn(startTimeMs).when(mDependencies).elapsedRealtime(); + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, + mNetworkQuirkMetrics, mDependencies); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); final int routerLifetime = 1000; final int prefixValidLifetime = 200; @@ -3293,23 +3309,24 @@ // Inject RA packets. Calling assertProgramUpdateAndGet()/assertNoProgramUpdate() is to make // sure that the RA packet has been processed. - apfFilter.pretendPacketReceived(ra1.build()); - program = ipClientCallback.assertProgramUpdateAndGet(); - apfFilter.pretendPacketReceived(ra2.build()); - program = ipClientCallback.assertProgramUpdateAndGet(); - apfFilter.pretendPacketReceived(raInvalid.build()); - ipClientCallback.assertNoProgramUpdate(); - apfFilter.pretendPacketReceived(raZeroRouterLifetime.build()); - ipClientCallback.assertProgramUpdateAndGet(); - apfFilter.pretendPacketReceived(raZeroPioValidLifetime.build()); - ipClientCallback.assertProgramUpdateAndGet(); - apfFilter.pretendPacketReceived(raZeroRdnssLifetime.build()); - ipClientCallback.assertProgramUpdateAndGet(); - apfFilter.pretendPacketReceived(raZeroRioRouteLifetime.build()); - ipClientCallback.assertProgramUpdateAndGet(); + pretendPacketReceived(ra1.build()); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); + pretendPacketReceived(ra2.build()); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); + pretendPacketReceived(raInvalid.build()); + Thread.sleep(NO_CALLBACK_TIMEOUT_MS); + verify(mIpClientCb, never()).installPacketFilter(any()); + pretendPacketReceived(raZeroRouterLifetime.build()); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); + pretendPacketReceived(raZeroPioValidLifetime.build()); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); + pretendPacketReceived(raZeroRdnssLifetime.build()); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); + pretendPacketReceived(raZeroRioRouteLifetime.build()); + consumeInstalledProgram(mIpClientCb, 1 /* installCnt */); // Write metrics data to statsd pipeline when shutdown. - doReturn(startTimeMs + durationTimeMs).when(mClock).elapsedRealtime(); + doReturn(startTimeMs + durationTimeMs).when(mDependencies).elapsedRealtime(); apfFilter.shutdown(); // Verify each metric fields in IpClientRaInfoMetrics. @@ -3324,26 +3341,25 @@ } private void verifyNoMetricsWrittenForShortDuration(boolean isLegacy) throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); final ApfConfiguration config = getDefaultConfig(); final long startTimeMs = 12345; final long durationTimeMs = config.minMetricsSessionDurationMs; // Verify no metrics data written to statsd for duration less than durationTimeMs. - doReturn(startTimeMs).when(mClock).elapsedRealtime(); - final TestAndroidPacketFilter apfFilter = makeTestApfFilter(config, ipClientCallback); - doReturn(startTimeMs + durationTimeMs - 1).when(mClock).elapsedRealtime(); + doReturn(startTimeMs).when(mDependencies).elapsedRealtime(); + final ApfFilter apfFilter = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, + mNetworkQuirkMetrics, mDependencies); + doReturn(startTimeMs + durationTimeMs - 1).when(mDependencies).elapsedRealtime(); apfFilter.shutdown(); verify(mApfSessionInfoMetrics, never()).statsWrite(); verify(mIpClientRaInfoMetrics, never()).statsWrite(); // Verify metrics data written to statsd for duration greater than or equal to // durationTimeMs. - ApfFilter.Clock clock = mock(ApfFilter.Clock.class); - doReturn(startTimeMs).when(clock).elapsedRealtime(); - final TestAndroidPacketFilter apfFilter2 = new TestApfFilter(mContext, config, - ipClientCallback, mNetworkQuirkMetrics, mDependencies, clock); - doReturn(startTimeMs + durationTimeMs).when(clock).elapsedRealtime(); + doReturn(startTimeMs).when(mDependencies).elapsedRealtime(); + final ApfFilter apfFilter2 = new ApfFilter(mContext, config, TEST_PARAMS, mIpClientCb, + mNetworkQuirkMetrics, mDependencies); + doReturn(startTimeMs + durationTimeMs).when(mDependencies).elapsedRealtime(); apfFilter2.shutdown(); verify(mApfSessionInfoMetrics).statsWrite(); verify(mIpClientRaInfoMetrics).statsWrite();
diff --git a/tests/unit/src/android/net/apf/ApfTestHelpers.kt b/tests/unit/src/android/net/apf/ApfTestHelpers.kt index b67ec05..30d5813 100644 --- a/tests/unit/src/android/net/apf/ApfTestHelpers.kt +++ b/tests/unit/src/android/net/apf/ApfTestHelpers.kt
@@ -74,6 +74,7 @@ return ret } + @JvmStatic fun consumeInstalledProgram( ipClientCb: IpClient.IpClientCallbacksWrapper, installCnt: Int
diff --git a/tests/unit/src/android/net/apf/ApfTestUtils.java b/tests/unit/src/android/net/apf/ApfTestUtils.java index e2a1b55..76fa5c9 100644 --- a/tests/unit/src/android/net/apf/ApfTestUtils.java +++ b/tests/unit/src/android/net/apf/ApfTestUtils.java
@@ -26,18 +26,13 @@ import static org.mockito.Mockito.mock; import android.content.Context; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.MacAddress; import android.net.apf.BaseApfGenerator.IllegalInstructionException; import android.net.ip.IIpClientCallbacks; import android.net.ip.IpClient; import android.net.metrics.IpConnectivityLog; import android.os.ConditionVariable; -import android.os.SystemClock; import android.system.ErrnoException; import android.system.Os; -import android.text.format.DateUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.HexDump; @@ -50,7 +45,6 @@ import java.io.FileDescriptor; import java.io.IOException; -import java.net.InetAddress; import java.util.Arrays; /** @@ -289,129 +283,6 @@ } /** - * The test apf filter class. - */ - public static class TestApfFilter extends ApfFilter implements TestAndroidPacketFilter { - public static final byte[] MOCK_MAC_ADDR = {2, 3, 4, 5, 6, 7}; - private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1}; - - private static final InterfaceParams LOCAL_PARAMS = InterfaceParams.getByName("lo"); - - private FileDescriptor mWriteSocket; - private long mCurrentTimeMs = SystemClock.elapsedRealtime(); - private final MockIpClientCallback mMockIpClientCb; - private final boolean mThrowsExceptionWhenGeneratesProgram; - - public TestApfFilter(Context context, ApfConfiguration config, - MockIpClientCallback ipClientCallback, NetworkQuirkMetrics networkQuirkMetrics, - Dependencies dependencies) throws Exception { - this(context, config, ipClientCallback, networkQuirkMetrics, dependencies, - false /* throwsExceptionWhenGeneratesProgram */, new ApfFilter.Clock()); - } - - public TestApfFilter(Context context, ApfConfiguration config, - MockIpClientCallback ipClientCallback, NetworkQuirkMetrics networkQuirkMetrics, - Dependencies dependencies, boolean throwsExceptionWhenGeneratesProgram) - throws Exception { - this(context, config, ipClientCallback, networkQuirkMetrics, dependencies, - throwsExceptionWhenGeneratesProgram, new ApfFilter.Clock()); - } - - public TestApfFilter(Context context, ApfConfiguration config, - MockIpClientCallback ipClientCallback, NetworkQuirkMetrics networkQuirkMetrics, - Dependencies dependencies, ApfFilter.Clock clock) throws Exception { - this(context, config, ipClientCallback, networkQuirkMetrics, dependencies, - false /* throwsExceptionWhenGeneratesProgram */, clock); - } - - public TestApfFilter(Context context, ApfConfiguration config, - MockIpClientCallback ipClientCallback, NetworkQuirkMetrics networkQuirkMetrics, - Dependencies dependencies, boolean throwsExceptionWhenGeneratesProgram, - ApfFilter.Clock clock) throws Exception { - super(context, config, new InterfaceParams("lo", LOCAL_PARAMS.index, - MacAddress.fromBytes(MOCK_MAC_ADDR)), ipClientCallback, - networkQuirkMetrics, dependencies, clock); - mMockIpClientCb = ipClientCallback; - mThrowsExceptionWhenGeneratesProgram = throwsExceptionWhenGeneratesProgram; - } - - /** - * Create a new test ApfFiler. - */ - public static ApfFilter createTestApfFilter(Context context, - MockIpClientCallback ipClientCallback, ApfConfiguration config, - NetworkQuirkMetrics networkQuirkMetrics, ApfFilter.Dependencies dependencies) - throws Exception { - LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); - LinkProperties lp = new LinkProperties(); - lp.addLinkAddress(link); - TestApfFilter apfFilter = new TestApfFilter(context, config, ipClientCallback, - networkQuirkMetrics, dependencies); - apfFilter.setLinkProperties(lp); - return apfFilter; - } - - /** - * Pretend an RA packet has been received and show it to ApfFilter. - */ - public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException { - mMockIpClientCb.resetApfProgramWait(); - // ApfFilter's ReceiveThread will be waiting to read this. - Os.write(mWriteSocket, packet, 0, packet.length); - } - - /** - * Simulate current time changes. - */ - public void increaseCurrentTimeSeconds(int delta) { - mCurrentTimeMs += delta * DateUtils.SECOND_IN_MILLIS; - } - - @Override - protected int secondsSinceBoot() { - return (int) (mCurrentTimeMs / DateUtils.SECOND_IN_MILLIS); - } - - @Override - public synchronized void startFilter() { - installNewProgramLocked(); - - // Create two sockets, "readSocket" and "mWriteSocket" and connect them together. - FileDescriptor readSocket = new FileDescriptor(); - mWriteSocket = new FileDescriptor(); - try { - Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket); - } catch (ErrnoException e) { - fail(); - return; - } - // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs. - // This allows us to pretend RA packets have been received via pretendPacketReceived(). - mReceiveThread = new ReceiveThread(readSocket); - mReceiveThread.start(); - } - - @Override - public synchronized void shutdown() { - super.shutdown(); - if (mReceiveThread != null) { - mReceiveThread.halt(); - mReceiveThread = null; - } - IoUtils.closeQuietly(mWriteSocket); - } - - @Override - @GuardedBy("this") - protected ApfV4GeneratorBase<?> emitPrologueLocked() throws IllegalInstructionException { - if (mThrowsExceptionWhenGeneratesProgram) { - throw new IllegalStateException(); - } - return super.emitPrologueLocked(); - } - } - - /** * The test legacy apf filter class. */ public static class TestLegacyApfFilter extends LegacyApfFilter