Merge "Increased the timeout from 5 to 30 seconds"
diff --git a/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
index fbb342d..846abcb 100644
--- a/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
+++ b/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
@@ -295,8 +295,7 @@
                 NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY);
         if (h1 == null) return false;
 
-        sendIpv4NfGenMsg(h1, (short) ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET),
-                           (short) (NLM_F_REQUEST | NLM_F_DUMP));
+        requestSocketDump(h1);
 
         final NativeHandle h2 = mDeps.createConntrackSocket(
                 NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
@@ -325,7 +324,7 @@
     }
 
     @VisibleForTesting
-    public void sendIpv4NfGenMsg(@NonNull NativeHandle handle, short type, short flags) {
+    void sendIpv4NfGenMsg(@NonNull NativeHandle handle, short type, short flags) {
         final int length = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE;
         final byte[] msg = new byte[length];
         final ByteBuffer byteBuffer = ByteBuffer.wrap(msg);
@@ -350,6 +349,12 @@
         }
     }
 
+    @VisibleForTesting
+    void requestSocketDump(NativeHandle handle) {
+        sendIpv4NfGenMsg(handle, (short) ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET),
+                (short) (NLM_F_REQUEST | NLM_F_DUMP));
+    }
+
     private void closeFdInNativeHandle(final NativeHandle h) {
         try {
             h.close();
diff --git a/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java b/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
index d38a7c3..23fb60c 100644
--- a/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
+++ b/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
@@ -16,28 +16,32 @@
 
 package com.android.networkstack.tethering;
 
+import static android.system.OsConstants.EAGAIN;
+import static android.system.OsConstants.IPPROTO_TCP;
+import static android.system.OsConstants.NETLINK_NETFILTER;
+
 import static com.android.net.module.util.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.IPCTNL_MSG_CT_GET;
 import static com.android.networkstack.tethering.OffloadHardwareInterface.IPCTNL_MSG_CT_NEW;
 import static com.android.networkstack.tethering.OffloadHardwareInterface.NFNL_SUBSYS_CTNETLINK;
 import static com.android.networkstack.tethering.OffloadHardwareInterface.NF_NETLINK_CONNTRACK_DESTROY;
 import static com.android.networkstack.tethering.OffloadHardwareInterface.NF_NETLINK_CONNTRACK_NEW;
 
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.NativeHandle;
-import android.system.Os;
+import android.system.ErrnoException;
+import android.util.Log;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.net.module.util.SharedLog;
+import com.android.net.module.util.netlink.ConntrackMessage;
+import com.android.net.module.util.netlink.NetlinkMessage;
+import com.android.net.module.util.netlink.NetlinkSocket;
 import com.android.net.module.util.netlink.StructNlMsgHdr;
 
 import org.junit.Before;
@@ -45,18 +49,18 @@
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
 
+import java.io.FileDescriptor;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
-import java.net.SocketAddress;
 import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class ConntrackSocketTest {
     private static final long TIMEOUT = 500;
+    private static final String TAG = ConntrackSocketTest.class.getSimpleName();
 
     private HandlerThread mHandlerThread;
     private Handler mHandler;
@@ -80,51 +84,72 @@
         mOffloadHw = new OffloadHardwareInterface(mHandler, mLog, mDeps);
     }
 
+    void findConnectionOrThrow(FileDescriptor fd, InetSocketAddress local, InetSocketAddress remote)
+            throws Exception {
+        Log.d(TAG, "Looking for socket " + local + " -> " + remote);
+
+        // Loop until the socket is found (and return) or recvMessage throws an exception.
+        while (true) {
+            final ByteBuffer buffer = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT);
+
+            // Parse all the netlink messages in the dump.
+            // NetlinkMessage#parse returns null if the message is truncated or invalid.
+            while (buffer.remaining() > 0) {
+                NetlinkMessage nlmsg = NetlinkMessage.parse(buffer, NETLINK_NETFILTER);
+                Log.d(TAG, "Got netlink message: " + nlmsg);
+                if (!(nlmsg instanceof ConntrackMessage)) {
+                    continue;
+                }
+
+                StructNlMsgHdr nlmsghdr = nlmsg.getHeader();
+                ConntrackMessage ctmsg = (ConntrackMessage) nlmsg;
+                ConntrackMessage.Tuple tuple = ctmsg.tupleOrig;
+
+                if (nlmsghdr.nlmsg_type == (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_NEW)
+                        && tuple.protoNum == IPPROTO_TCP
+                        && tuple.srcIp.equals(local.getAddress())
+                        && tuple.dstIp.equals(remote.getAddress())
+                        && tuple.srcPort == (short) local.getPort()
+                        && tuple.dstPort == (short) remote.getPort()) {
+                    return;
+                }
+            }
+        }
+    }
+
     @Test
     public void testIpv4ConntrackSocket() throws Exception {
         // Set up server and connect.
-        final InetSocketAddress anyAddress = new InetSocketAddress(
-                InetAddress.getByName("127.0.0.1"), 0);
+        final InetAddress localhost = InetAddress.getByName("127.0.0.1");
+        final InetSocketAddress anyAddress = new InetSocketAddress(localhost, 0);
         final ServerSocket serverSocket = new ServerSocket();
         serverSocket.bind(anyAddress);
-        final SocketAddress theAddress = serverSocket.getLocalSocketAddress();
+        final InetSocketAddress theAddress =
+                (InetSocketAddress) serverSocket.getLocalSocketAddress();
 
         // Make a connection to the server.
         final Socket socket = new Socket();
         socket.connect(theAddress);
+        final InetSocketAddress localAddress = (InetSocketAddress) socket.getLocalSocketAddress();
         final Socket acceptedSocket = serverSocket.accept();
 
         final NativeHandle handle = mDeps.createConntrackSocket(
                 NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY);
-        mOffloadHw.sendIpv4NfGenMsg(handle,
-                (short) ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET),
-                (short) (NLM_F_REQUEST | NLM_F_DUMP));
-
-        boolean foundConntrackEntry = false;
-        ByteBuffer buffer = ByteBuffer.allocate(DEFAULT_RECV_BUFSIZE);
-        buffer.order(ByteOrder.nativeOrder());
+        mOffloadHw.requestSocketDump(handle);
 
         try {
-            while (Os.read(handle.getFileDescriptor(), buffer) > 0) {
-                buffer.flip();
-
-                // TODO: ConntrackMessage should get a parse API like StructNlMsgHdr
-                // so we can confirm that the conntrack added is for the TCP connection above.
-                final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(buffer);
-                assertNotNull(nlmsghdr);
-
-                // As long as 1 conntrack entry is found test case will pass, even if it's not
-                // the from the TCP connection above.
-                if (nlmsghdr.nlmsg_type == ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW)) {
-                    foundConntrackEntry = true;
-                    break;
-                }
+            findConnectionOrThrow(handle.getFileDescriptor(), localAddress, theAddress);
+            // No exceptions? Socket was found, test passes.
+        } catch (ErrnoException e) {
+            if (e.errno == EAGAIN) {
+                fail("Did not find socket " + localAddress + "->" + theAddress + " in dump");
+            } else {
+                throw e;
             }
         } finally {
             socket.close();
             serverSocket.close();
+            acceptedSocket.close();
         }
-        assertTrue("Did not receive any NFNL_SUBSYS_CTNETLINK/IPCTNL_MSG_CT_NEW message",
-                foundConntrackEntry);
     }
 }
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 437622b..8ed735a 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -66,7 +66,6 @@
         "java/android/net/netstats/NetworkStatsDataMigrationUtilsTest.kt",
         "java/com/android/internal/net/NetworkUtilsInternalTest.java",
         "java/com/android/internal/net/VpnProfileTest.java",
-        "java/com/android/server/NetworkManagementServiceTest.java",
         "java/com/android/server/VpnManagerServiceTest.java",
         "java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java",
         "java/com/android/server/connectivity/IpConnectivityMetricsTest.java",
diff --git a/tests/unit/java/com/android/server/NetworkManagementServiceTest.java b/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
deleted file mode 100644
index 7688a6b..0000000
--- a/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
-import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
-import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
-import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
-import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
-import static android.util.DebugUtils.valueToString;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.INetd;
-import android.net.INetdUnsolicitedEventListener;
-import android.net.LinkAddress;
-import android.net.NetworkPolicyManager;
-import android.os.BatteryStats;
-import android.os.Binder;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.Process;
-import android.os.RemoteException;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.ArrayMap;
-
-import com.android.internal.app.IBatteryStats;
-import com.android.server.NetworkManagementService.Dependencies;
-import com.android.server.net.BaseNetworkObserver;
-import com.android.testutils.DevSdkIgnoreRule;
-import com.android.testutils.DevSdkIgnoreRunner;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.function.BiFunction;
-
-/**
- * Tests for {@link NetworkManagementService}.
- */
-@RunWith(DevSdkIgnoreRunner.class)
-@SmallTest
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
-public class NetworkManagementServiceTest {
-    private NetworkManagementService mNMService;
-    @Mock private Context mContext;
-    @Mock private ConnectivityManager mCm;
-    @Mock private IBatteryStats.Stub mBatteryStatsService;
-    @Mock private INetd.Stub mNetdService;
-
-    private static final int TEST_UID = 111;
-
-    @NonNull
-    @Captor
-    private ArgumentCaptor<INetdUnsolicitedEventListener> mUnsolListenerCaptor;
-
-    private final MockDependencies mDeps = new MockDependencies();
-
-    private final class MockDependencies extends Dependencies {
-        @Override
-        public IBinder getService(String name) {
-            switch (name) {
-                case BatteryStats.SERVICE_NAME:
-                    return mBatteryStatsService;
-                default:
-                    throw new UnsupportedOperationException("Unknown service " + name);
-            }
-        }
-
-        @Override
-        public void registerLocalService(NetworkManagementInternal nmi) {
-        }
-
-        @Override
-        public INetd getNetd() {
-            return mNetdService;
-        }
-
-        @Override
-        public int getCallingUid() {
-            return Process.SYSTEM_UID;
-        }
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        doNothing().when(mNetdService)
-                .registerUnsolicitedEventListener(mUnsolListenerCaptor.capture());
-        doReturn(Context.CONNECTIVITY_SERVICE).when(mContext).getSystemServiceName(
-                eq(ConnectivityManager.class));
-        doReturn(mCm).when(mContext).getSystemService(eq(Context.CONNECTIVITY_SERVICE));
-        // Start the service and wait until it connects to our socket.
-        mNMService = NetworkManagementService.create(mContext, mDeps);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        mNMService.shutdown();
-    }
-
-    private static <T> T expectSoon(T mock) {
-        return verify(mock, timeout(200));
-    }
-
-    /**
-     * Tests that network observers work properly.
-     */
-    @Test
-    public void testNetworkObservers() throws Exception {
-        BaseNetworkObserver observer = mock(BaseNetworkObserver.class);
-        doReturn(new Binder()).when(observer).asBinder();  // Used by registerObserver.
-        mNMService.registerObserver(observer);
-
-        // Forget everything that happened to the mock so far, so we can explicitly verify
-        // everything that happens and does not happen to it from now on.
-
-        INetdUnsolicitedEventListener unsolListener = mUnsolListenerCaptor.getValue();
-        reset(observer);
-        // Now call unsolListener methods and ensure that the observer methods are
-        // called. After every method we expect a callback soon after; to ensure that
-        // invalid messages don't cause any callbacks, we call verifyNoMoreInteractions at the end.
-
-        /**
-         * Interface changes.
-         */
-        unsolListener.onInterfaceAdded("rmnet12");
-        expectSoon(observer).interfaceAdded("rmnet12");
-
-        unsolListener.onInterfaceRemoved("eth1");
-        expectSoon(observer).interfaceRemoved("eth1");
-
-        unsolListener.onInterfaceChanged("clat4", true);
-        expectSoon(observer).interfaceStatusChanged("clat4", true);
-
-        unsolListener.onInterfaceLinkStateChanged("rmnet0", false);
-        expectSoon(observer).interfaceLinkStateChanged("rmnet0", false);
-
-        /**
-         * Bandwidth control events.
-         */
-        unsolListener.onQuotaLimitReached("data", "rmnet_usb0");
-        expectSoon(observer).limitReached("data", "rmnet_usb0");
-
-        /**
-         * Interface class activity.
-         */
-        unsolListener.onInterfaceClassActivityChanged(true, 1, 1234, TEST_UID);
-        expectSoon(observer).interfaceClassDataActivityChanged(1, true, 1234, TEST_UID);
-
-        unsolListener.onInterfaceClassActivityChanged(false, 9, 5678, TEST_UID);
-        expectSoon(observer).interfaceClassDataActivityChanged(9, false, 5678, TEST_UID);
-
-        unsolListener.onInterfaceClassActivityChanged(false, 9, 4321, TEST_UID);
-        expectSoon(observer).interfaceClassDataActivityChanged(9, false, 4321, TEST_UID);
-
-        /**
-         * IP address changes.
-         */
-        unsolListener.onInterfaceAddressUpdated("fe80::1/64", "wlan0", 128, 253);
-        expectSoon(observer).addressUpdated("wlan0", new LinkAddress("fe80::1/64", 128, 253));
-
-        unsolListener.onInterfaceAddressRemoved("fe80::1/64", "wlan0", 128, 253);
-        expectSoon(observer).addressRemoved("wlan0", new LinkAddress("fe80::1/64", 128, 253));
-
-        unsolListener.onInterfaceAddressRemoved("2001:db8::1/64", "wlan0", 1, 0);
-        expectSoon(observer).addressRemoved("wlan0", new LinkAddress("2001:db8::1/64", 1, 0));
-
-        /**
-         * DNS information broadcasts.
-         */
-        unsolListener.onInterfaceDnsServerInfo("rmnet_usb0", 3600, new String[]{"2001:db8::1"});
-        expectSoon(observer).interfaceDnsServerInfo("rmnet_usb0", 3600,
-                new String[]{"2001:db8::1"});
-
-        unsolListener.onInterfaceDnsServerInfo("wlan0", 14400,
-                new String[]{"2001:db8::1", "2001:db8::2"});
-        expectSoon(observer).interfaceDnsServerInfo("wlan0", 14400,
-                new String[]{"2001:db8::1", "2001:db8::2"});
-
-        // We don't check for negative lifetimes, only for parse errors.
-        unsolListener.onInterfaceDnsServerInfo("wlan0", -3600, new String[]{"::1"});
-        expectSoon(observer).interfaceDnsServerInfo("wlan0", -3600,
-                new String[]{"::1"});
-
-        // No syntax checking on the addresses.
-        unsolListener.onInterfaceDnsServerInfo("wlan0", 600,
-                new String[]{"", "::", "", "foo", "::1"});
-        expectSoon(observer).interfaceDnsServerInfo("wlan0", 600,
-                new String[]{"", "::", "", "foo", "::1"});
-
-        // Make sure nothing else was called.
-        verifyNoMoreInteractions(observer);
-    }
-
-    @Test
-    public void testFirewallEnabled() {
-        mNMService.setFirewallEnabled(true);
-        assertTrue(mNMService.isFirewallEnabled());
-
-        mNMService.setFirewallEnabled(false);
-        assertFalse(mNMService.isFirewallEnabled());
-    }
-
-    @Test
-    public void testNetworkRestrictedDefault() {
-        assertFalse(mNMService.isNetworkRestricted(TEST_UID));
-    }
-
-    @Test
-    public void testMeteredNetworkRestrictions() throws RemoteException {
-        // Make sure the mocked netd method returns true.
-        doReturn(true).when(mNetdService).bandwidthEnableDataSaver(anyBoolean());
-
-        // Restrict usage of mobile data in background
-        mNMService.setUidOnMeteredNetworkDenylist(TEST_UID, true);
-        assertTrue("Should be true since mobile data usage is restricted",
-                mNMService.isNetworkRestricted(TEST_UID));
-        verify(mCm).addUidToMeteredNetworkDenyList(TEST_UID);
-
-        mNMService.setDataSaverModeEnabled(true);
-        verify(mNetdService).bandwidthEnableDataSaver(true);
-
-        mNMService.setUidOnMeteredNetworkDenylist(TEST_UID, false);
-        assertTrue("Should be true since data saver is on and the uid is not allowlisted",
-                mNMService.isNetworkRestricted(TEST_UID));
-        verify(mCm).removeUidFromMeteredNetworkDenyList(TEST_UID);
-
-        mNMService.setUidOnMeteredNetworkAllowlist(TEST_UID, true);
-        assertFalse("Should be false since data saver is on and the uid is allowlisted",
-                mNMService.isNetworkRestricted(TEST_UID));
-        verify(mCm).addUidToMeteredNetworkAllowList(TEST_UID);
-
-        // remove uid from allowlist and turn datasaver off again
-        mNMService.setUidOnMeteredNetworkAllowlist(TEST_UID, false);
-        verify(mCm).removeUidFromMeteredNetworkAllowList(TEST_UID);
-        mNMService.setDataSaverModeEnabled(false);
-        verify(mNetdService).bandwidthEnableDataSaver(false);
-        assertFalse("Network should not be restricted when data saver is off",
-                mNMService.isNetworkRestricted(TEST_UID));
-    }
-
-    @Test
-    public void testFirewallChains() {
-        final ArrayMap<Integer, ArrayMap<Integer, Boolean>> expected = new ArrayMap<>();
-        // Dozable chain
-        final ArrayMap<Integer, Boolean> isRestrictedForDozable = new ArrayMap<>();
-        isRestrictedForDozable.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
-        isRestrictedForDozable.put(INetd.FIREWALL_RULE_ALLOW, false);
-        isRestrictedForDozable.put(INetd.FIREWALL_RULE_DENY, true);
-        expected.put(FIREWALL_CHAIN_DOZABLE, isRestrictedForDozable);
-        // Powersaver chain
-        final ArrayMap<Integer, Boolean> isRestrictedForPowerSave = new ArrayMap<>();
-        isRestrictedForPowerSave.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
-        isRestrictedForPowerSave.put(INetd.FIREWALL_RULE_ALLOW, false);
-        isRestrictedForPowerSave.put(INetd.FIREWALL_RULE_DENY, true);
-        expected.put(FIREWALL_CHAIN_POWERSAVE, isRestrictedForPowerSave);
-        // Standby chain
-        final ArrayMap<Integer, Boolean> isRestrictedForStandby = new ArrayMap<>();
-        isRestrictedForStandby.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, false);
-        isRestrictedForStandby.put(INetd.FIREWALL_RULE_ALLOW, false);
-        isRestrictedForStandby.put(INetd.FIREWALL_RULE_DENY, true);
-        expected.put(FIREWALL_CHAIN_STANDBY, isRestrictedForStandby);
-        // Restricted mode chain
-        final ArrayMap<Integer, Boolean> isRestrictedForRestrictedMode = new ArrayMap<>();
-        isRestrictedForRestrictedMode.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
-        isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_ALLOW, false);
-        isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_DENY, true);
-        expected.put(FIREWALL_CHAIN_RESTRICTED, isRestrictedForRestrictedMode);
-        // Low Power Standby chain
-        final ArrayMap<Integer, Boolean> isRestrictedForLowPowerStandby = new ArrayMap<>();
-        isRestrictedForLowPowerStandby.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
-        isRestrictedForLowPowerStandby.put(INetd.FIREWALL_RULE_ALLOW, false);
-        isRestrictedForLowPowerStandby.put(INetd.FIREWALL_RULE_DENY, true);
-        expected.put(FIREWALL_CHAIN_LOW_POWER_STANDBY, isRestrictedForLowPowerStandby);
-
-        final int[] chains = {
-                FIREWALL_CHAIN_STANDBY,
-                FIREWALL_CHAIN_POWERSAVE,
-                FIREWALL_CHAIN_DOZABLE,
-                FIREWALL_CHAIN_RESTRICTED,
-                FIREWALL_CHAIN_LOW_POWER_STANDBY
-        };
-        final int[] states = {
-                INetd.FIREWALL_RULE_ALLOW,
-                INetd.FIREWALL_RULE_DENY,
-                NetworkPolicyManager.FIREWALL_RULE_DEFAULT
-        };
-        BiFunction<Integer, Integer, String> errorMsg = (chain, state) -> {
-            return String.format("Unexpected value for chain: %s and state: %s",
-                    valueToString(INetd.class, "FIREWALL_CHAIN_", chain),
-                    valueToString(INetd.class, "FIREWALL_RULE_", state));
-        };
-        for (int chain : chains) {
-            final ArrayMap<Integer, Boolean> expectedValues = expected.get(chain);
-            mNMService.setFirewallChainEnabled(chain, true);
-            verify(mCm).setFirewallChainEnabled(chain, true /* enabled */);
-            for (int state : states) {
-                mNMService.setFirewallUidRule(chain, TEST_UID, state);
-                assertEquals(errorMsg.apply(chain, state),
-                        expectedValues.get(state), mNMService.isNetworkRestricted(TEST_UID));
-            }
-            mNMService.setFirewallChainEnabled(chain, false);
-            verify(mCm).setFirewallChainEnabled(chain, false /* enabled */);
-        }
-    }
-}