Handling the light doze mode properly in ApfFilter
ApfFilter should treat light doze mode same as doze mode and install
more aggressive filter to save power in light doze mode.
Bug: 310055888
Test: TH
Change-Id: I191633833aca018e0037e9b43b8a6a292bfd664e
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java
index 41c6726..bb73b8c 100644
--- a/src/android/net/apf/ApfFilter.java
+++ b/src/android/net/apf/ApfFilter.java
@@ -17,6 +17,8 @@
package android.net.apf;
import static android.net.util.SocketUtils.makePacketSocketAddress;
+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_PACKET;
import static android.system.OsConstants.ARPHRD_ETHER;
import static android.system.OsConstants.ETH_P_ARP;
@@ -54,6 +56,7 @@
import android.util.Log;
import android.util.SparseArray;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.GuardedBy;
@@ -61,6 +64,7 @@
import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.TokenBucket;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.ConnectivityUtils;
import com.android.net.module.util.InterfaceParams;
@@ -112,6 +116,7 @@
public int[] ethTypeBlackList;
public int minRdnssLifetimeSec;
public int acceptRaMinLft;
+ public boolean shouldHandleLightDoze;
}
/**
@@ -323,16 +328,48 @@
// Tracks the value of /proc/sys/ipv6/conf/$iface/accept_ra_min_lft which affects router, RIO,
// and PIO valid lifetimes.
private final int mAcceptRaMinLft;
+ private final boolean mShouldHandleLightDoze;
+
+ private static boolean isDeviceIdleModeChangedAction(Intent intent) {
+ return ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction());
+ }
+
+ private boolean isDeviceLightIdleModeChangedAction(Intent intent) {
+ // The ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED only exist since T. For lower platform version,
+ // the check should return false. The explicit SDK check is needed to make linter happy
+ // about accessing ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED in this function.
+ if (!SdkLevel.isAtLeastT()) {
+ return false;
+ }
+ if (!mShouldHandleLightDoze) {
+ return false;
+ }
+ return ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED.equals(intent.getAction());
+ }
+
+ private boolean isDeviceLightIdleMode(@NonNull PowerManager powerManager) {
+ // The powerManager.isDeviceLightIdleMode() only exist since T. For lower platform version,
+ // the check should return false. The explicit SDK check is needed to make linter happy
+ // about accessing powerManager.isDeviceLightIdleMode() in this function.
+ if (!SdkLevel.isAtLeastT()) {
+ return false;
+ }
+ if (!mShouldHandleLightDoze) {
+ return false;
+ }
+
+ return powerManager.isDeviceLightIdleMode();
+ }
// Detects doze mode state transitions.
private final BroadcastReceiver mDeviceIdleReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) {
- PowerManager powerManager =
- (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- final boolean deviceIdle = powerManager.isDeviceIdleMode();
+ final PowerManager powerManager = context.getSystemService(PowerManager.class);
+ if (isDeviceIdleModeChangedAction(intent)
+ || isDeviceLightIdleModeChangedAction(intent)) {
+ final boolean deviceIdle = powerManager.isDeviceIdleMode()
+ || isDeviceLightIdleMode(powerManager);
setDozeMode(deviceIdle);
}
}
@@ -346,9 +383,16 @@
@GuardedBy("this")
private int mIPv4PrefixLength;
- @VisibleForTesting
+ private final Dependencies mDependencies;
+
public ApfFilter(Context context, ApfConfiguration config, InterfaceParams ifParams,
IpClientCallbacksWrapper ipClientCallback) {
+ this(context, config, ifParams, ipClientCallback, new Dependencies(context));
+ }
+
+ @VisibleForTesting
+ public ApfFilter(Context context, ApfConfiguration config, InterfaceParams ifParams,
+ IpClientCallbacksWrapper ipClientCallback, Dependencies dependencies) {
mApfCapabilities = config.apfCapabilities;
mIpClientCallback = ipClientCallback;
mInterfaceParams = ifParams;
@@ -357,6 +401,8 @@
mMinRdnssLifetimeSec = config.minRdnssLifetimeSec;
mAcceptRaMinLft = config.acceptRaMinLft;
mContext = context;
+ mShouldHandleLightDoze = config.shouldHandleLightDoze;
+ mDependencies = dependencies;
if (mApfCapabilities.hasDataAccess()) {
mCountAndPassLabel = "countAndPass";
@@ -384,8 +430,33 @@
maybeStartFilter();
// Listen for doze-mode transition changes to enable/disable the IPv6 multicast filter.
- mContext.registerReceiver(mDeviceIdleReceiver,
- new IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED));
+ mDependencies.addDeviceIdleReceiver(mDeviceIdleReceiver, mShouldHandleLightDoze);
+ }
+
+ /**
+ * Dependencies class for testing.
+ */
+ @VisibleForTesting
+ public static class Dependencies {
+ private final Context mContext;
+ public Dependencies(final Context context) {
+ mContext = context;
+ }
+
+ /** Add receiver for detecting doze mode change */
+ public void addDeviceIdleReceiver(@NonNull final BroadcastReceiver receiver,
+ boolean shouldHandleLightDoze) {
+ final IntentFilter intentFilter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED);
+ if (SdkLevel.isAtLeastT() && shouldHandleLightDoze) {
+ intentFilter.addAction(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED);
+ }
+ mContext.registerReceiver(receiver, intentFilter);
+ }
+
+ /** Remove broadcast receiver. */
+ public void removeBroadcastReceiver(@NonNull final BroadcastReceiver receiver) {
+ mContext.unregisterReceiver(receiver);
+ }
}
public synchronized void setDataSnapshot(byte[] data) {
@@ -2052,7 +2123,7 @@
mReceiveThread = null;
}
mRas.clear();
- mContext.unregisterReceiver(mDeviceIdleReceiver);
+ mDependencies.removeBroadcastReceiver(mDeviceIdleReceiver);
}
public synchronized void setMulticastFilter(boolean isEnabled) {
@@ -2087,6 +2158,11 @@
installNewProgramLocked();
}
+ @VisibleForTesting
+ public synchronized boolean isInDozeMode() {
+ return mInDozeMode;
+ }
+
/** Find the single IPv4 LinkAddress if there is one, otherwise return null. */
private static LinkAddress findIPv4LinkAddress(LinkProperties lp) {
LinkAddress ipv4Address = null;
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java
index b7a6eda..fc99afe 100644
--- a/src/android/net/ip/IpClient.java
+++ b/src/android/net/ip/IpClient.java
@@ -40,6 +40,7 @@
import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_ROUTERS_MULTICAST;
import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH;
import static com.android.net.module.util.NetworkStackConstants.VENDOR_SPECIFIC_IE_ID;
+import static com.android.networkstack.util.NetworkStackUtils.APF_HANDLE_LIGHT_DOZE_FORCE_DISABLE;
import static com.android.networkstack.util.NetworkStackUtils.APF_NEW_RA_FILTER_VERSION;
import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_DHCPV6_PREFIX_DELEGATION_VERSION;
import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_GARP_NA_ROAMING_VERSION;
@@ -671,6 +672,7 @@
private final boolean mDhcp6PrefixDelegationEnabled;
private final boolean mUseNewApfFilter;
private final boolean mEnableIpClientIgnoreLowRaLifetime;
+ private final boolean mApfShouldHandleLightDoze;
private InterfaceParams mInterfaceParams;
@@ -890,6 +892,9 @@
mUseNewApfFilter = mDependencies.isFeatureEnabled(context, APF_NEW_RA_FILTER_VERSION);
mEnableIpClientIgnoreLowRaLifetime = mDependencies.isFeatureEnabled(context,
IPCLIENT_IGNORE_LOW_RA_LIFETIME_VERSION);
+ // Light doze mode status checking API is only available at T or later releases.
+ mApfShouldHandleLightDoze = SdkLevel.isAtLeastT() && mDependencies.isFeatureNotChickenedOut(
+ mContext, APF_HANDLE_LIGHT_DOZE_FORCE_DISABLE);
IpClientLinkObserver.Configuration config = new IpClientLinkObserver.Configuration(
mMinRdnssLifetimeSec);
@@ -2359,6 +2364,7 @@
apfConfig.minRdnssLifetimeSec = mMinRdnssLifetimeSec;
apfConfig.acceptRaMinLft = mAcceptRaMinLft;
+ apfConfig.shouldHandleLightDoze = mApfShouldHandleLightDoze;
return mDependencies.maybeCreateApfFilter(mContext, apfConfig, mInterfaceParams,
mCallback, mUseNewApfFilter);
}
diff --git a/src/com/android/networkstack/util/NetworkStackUtils.java b/src/com/android/networkstack/util/NetworkStackUtils.java
index 152a8fe..84a4491 100755
--- a/src/com/android/networkstack/util/NetworkStackUtils.java
+++ b/src/com/android/networkstack/util/NetworkStackUtils.java
@@ -265,6 +265,11 @@
public static final String IPCLIENT_PARSE_NETLINK_EVENTS_FORCE_DISABLE =
"ipclient_parse_netlink_events_force_disable";
+ /**
+ * Kill switch flag to disable the feature of handle light doze mode in Apf.
+ */
+ public static final String APF_HANDLE_LIGHT_DOZE_FORCE_DISABLE =
+ "apf_handle_light_doze_force_disable";
/**
* Kill switch flag to disable the feature of skipping Tcp socket info polling when light
diff --git a/tests/unit/src/android/net/apf/ApfTest.java b/tests/unit/src/android/net/apf/ApfTest.java
index 86d1333..4d22219 100644
--- a/tests/unit/src/android/net/apf/ApfTest.java
+++ b/tests/unit/src/android/net/apf/ApfTest.java
@@ -25,6 +25,8 @@
import static android.net.apf.ApfTestUtils.MIN_PKT_SIZE;
import static android.net.apf.ApfTestUtils.PASS;
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.ARPHRD_ETHER;
import static android.system.OsConstants.ETH_P_ARP;
import static android.system.OsConstants.ETH_P_IP;
@@ -37,10 +39,16 @@
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.LinkAddress;
@@ -52,6 +60,8 @@
import android.net.apf.ApfGenerator.IllegalInstructionException;
import android.net.apf.ApfTestUtils.MockIpClientCallback;
import android.net.apf.ApfTestUtils.TestApfFilter;
+import android.os.Build;
+import android.os.PowerManager;
import android.system.ErrnoException;
import android.text.TextUtils;
import android.util.Log;
@@ -66,14 +76,18 @@
import com.android.net.module.util.NetworkStackConstants;
import com.android.net.module.util.PacketBuilder;
import com.android.server.networkstack.tests.R;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import libcore.io.Streams;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -99,11 +113,13 @@
*
* The test cases will be executed by both APFv4 and APFv6 interpreter.
*/
-@RunWith(Parameterized.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
public class ApfTest {
private static final int MIN_APF_VERSION = 2;
+ @Rule
+ public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule();
// Indicates which apf interpreter to run.
@Parameterized.Parameter()
public int mApfVersion;
@@ -113,10 +129,14 @@
return Arrays.asList(4, 6);
}
- @Mock Context mContext;
+ @Mock private Context mContext;
+ @Mock
+ private ApfFilter.Dependencies mDependencies;
+ @Mock private PowerManager mPowerManager;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
}
private static final String TAG = "ApfTest";
@@ -1030,17 +1050,6 @@
private static final int IPV6_UDP_DEST_PORT_OFFSET = IPV6_PAYLOAD_OFFSET + 2;
private static final int MDNS_UDP_PORT = 5353;
- // Helper to initialize a default apfFilter.
- private ApfFilter setupApfFilter(
- MockIpClientCallback ipClientCallback, ApfConfiguration config) throws Exception {
- LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
- LinkProperties lp = new LinkProperties();
- lp.addLinkAddress(link);
- TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback);
- apfFilter.setLinkProperties(lp);
- return apfFilter;
- }
-
private static void setIpv4VersionFields(ByteBuffer packet) {
packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IP);
packet.put(IP_HEADER_OFFSET, (byte) 0x45);
@@ -1696,20 +1705,60 @@
@Test
public void testApfFilterMulticastPingWhileDozing() throws Exception {
- MockIpClientCallback ipClientCallback = new MockIpClientCallback();
- ApfFilter apfFilter = setupApfFilter(ipClientCallback, getDefaultConfig());
+ doTestApfFilterMulticastPingWhileDozing(false /* isLightDozing */);
+ }
+
+ @Test
+ @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ public void testApfFilterMulticastPingWhileLightDozing() throws Exception {
+ doTestApfFilterMulticastPingWhileDozing(true /* isLightDozing */);
+ }
+
+ @Test
+ @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ public void testShouldHandleLightDozeKillSwitch() throws Exception {
+ final MockIpClientCallback ipClientCallback = new MockIpClientCallback();
+ final ApfConfiguration configuration = getDefaultConfig();
+ configuration.shouldHandleLightDoze = false;
+ final ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback,
+ configuration, mDependencies);
+ final ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mDependencies).addDeviceIdleReceiver(receiverCaptor.capture(), anyBoolean());
+ final BroadcastReceiver receiver = receiverCaptor.getValue();
+ doReturn(true).when(mPowerManager).isDeviceLightIdleMode();
+ receiver.onReceive(mContext, new Intent(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED));
+ assertFalse(apfFilter.isInDozeMode());
+ }
+
+ private void doTestApfFilterMulticastPingWhileDozing(boolean isLightDozing) throws Exception {
+ final MockIpClientCallback ipClientCallback = new MockIpClientCallback();
+ final ApfConfiguration configuration = getDefaultConfig();
+ configuration.shouldHandleLightDoze = true;
+ final ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback,
+ configuration, mDependencies);
+ final ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mDependencies).addDeviceIdleReceiver(receiverCaptor.capture(), anyBoolean());
+ final BroadcastReceiver receiver = receiverCaptor.getValue();
// Construct a multicast ICMPv6 ECHO request.
final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
- ByteBuffer packet = makeIpv6Packet(IPPROTO_ICMPV6);
+ final ByteBuffer packet = makeIpv6Packet(IPPROTO_ICMPV6);
packet.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ECHO_REQUEST_TYPE);
put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
// Normally, we let multicast pings alone...
assertPass(ipClientCallback.assertProgramUpdateAndGet(), packet.array());
+ if (isLightDozing) {
+ doReturn(true).when(mPowerManager).isDeviceLightIdleMode();
+ receiver.onReceive(mContext, new Intent(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED));
+ } else {
+ doReturn(true).when(mPowerManager).isDeviceIdleMode();
+ receiver.onReceive(mContext, new Intent(ACTION_DEVICE_IDLE_MODE_CHANGED));
+ }
// ...and even while dozing...
- apfFilter.setDozeMode(true);
assertPass(ipClientCallback.assertProgramUpdateAndGet(), packet.array());
// ...but when the multicast filter is also enabled, drop the multicast pings to save power.
@@ -1725,7 +1774,13 @@
// Now wake up from doze mode to ensure that we no longer drop the packets.
// (The multicast filter is still enabled at this point).
- apfFilter.setDozeMode(false);
+ if (isLightDozing) {
+ doReturn(false).when(mPowerManager).isDeviceLightIdleMode();
+ receiver.onReceive(mContext, new Intent(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED));
+ } else {
+ doReturn(false).when(mPowerManager).isDeviceIdleMode();
+ receiver.onReceive(mContext, new Intent(ACTION_DEVICE_IDLE_MODE_CHANGED));
+ }
assertPass(ipClientCallback.assertProgramUpdateAndGet(), packet.array());
apfFilter.shutdown();
@@ -1735,7 +1790,8 @@
public void testApfFilter802_3() throws Exception {
MockIpClientCallback ipClientCallback = new MockIpClientCallback();
ApfConfiguration config = getDefaultConfig();
- ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
+ ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config,
+ mDependencies);
byte[] program = ipClientCallback.assertProgramUpdateAndGet();
// Verify empty packet of 100 zero bytes is passed
@@ -1755,7 +1811,8 @@
ipClientCallback.resetApfProgramWait();
apfFilter.shutdown();
config.ieee802_3Filter = DROP_802_3_FRAMES;
- apfFilter = setupApfFilter(ipClientCallback, config);
+ apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config,
+ mDependencies);
program = ipClientCallback.assertProgramUpdateAndGet();
// Verify that IEEE802.3 frame is dropped
@@ -1782,7 +1839,8 @@
MockIpClientCallback ipClientCallback = new MockIpClientCallback();
ApfConfiguration config = getDefaultConfig();
- ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
+ ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config,
+ mDependencies);
byte[] program = ipClientCallback.assertProgramUpdateAndGet();
// Verify empty packet of 100 zero bytes is passed
@@ -1802,7 +1860,8 @@
ipClientCallback.resetApfProgramWait();
apfFilter.shutdown();
config.ethTypeBlackList = ipv4BlackList;
- apfFilter = setupApfFilter(ipClientCallback, config);
+ apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config,
+ mDependencies);
program = ipClientCallback.assertProgramUpdateAndGet();
// Verify that IPv4 frame will be dropped
@@ -1817,7 +1876,8 @@
ipClientCallback.resetApfProgramWait();
apfFilter.shutdown();
config.ethTypeBlackList = ipv4Ipv6BlackList;
- apfFilter = setupApfFilter(ipClientCallback, config);
+ apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config,
+ mDependencies);
program = ipClientCallback.assertProgramUpdateAndGet();
// Verify that IPv4 frame will be dropped
diff --git a/tests/unit/src/android/net/apf/ApfTestUtils.java b/tests/unit/src/android/net/apf/ApfTestUtils.java
index 79f5283..69c4079 100644
--- a/tests/unit/src/android/net/apf/ApfTestUtils.java
+++ b/tests/unit/src/android/net/apf/ApfTestUtils.java
@@ -26,6 +26,8 @@
import static org.mockito.Mockito.mock;
import android.content.Context;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
import android.net.ip.IIpClientCallbacks;
import android.net.ip.IpClient;
import android.os.ConditionVariable;
@@ -43,6 +45,7 @@
import java.io.FileDescriptor;
import java.io.IOException;
+import java.net.InetAddress;
import java.util.Arrays;
/**
@@ -253,6 +256,7 @@
*/
public static class TestApfFilter extends ApfFilter {
public static final byte[] MOCK_MAC_ADDR = {1, 2, 3, 4, 5, 6};
+ private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1};
private FileDescriptor mWriteSocket;
private long mCurrentTimeMs = SystemClock.elapsedRealtime();
@@ -260,11 +264,31 @@
public TestApfFilter(Context context, ApfConfiguration config,
MockIpClientCallback ipClientCallback) throws Exception {
- super(context, config, InterfaceParams.getByName("lo"), ipClientCallback);
+ this(context, config, ipClientCallback, new Dependencies(context));
+ }
+
+ public TestApfFilter(Context context, ApfConfiguration config,
+ MockIpClientCallback ipClientCallback, Dependencies dependencies) {
+ super(context, config, InterfaceParams.getByName("lo"), ipClientCallback, dependencies);
mMockIpClientCb = ipClientCallback;
}
/**
+ * Create a new test ApfFiler.
+ */
+ public static ApfFilter createTestApfFilter(Context context,
+ MockIpClientCallback ipClientCallback, ApfConfiguration config,
+ 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,
+ 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 {