Don't leak map fds in BpfCoordinator#dump.

Currently, the dump methods open BpfMap objects and never close
them. This leaks filedescriptors, and if dump is called often
enough, will crash the networkstack process.

Fix this by using try-with-resources statements that
automatically close the map when exiting the try block.

Change the signature of BpfMap#close from "throws Exception" to
"throws ErrnoException" since it does not throw any other type
of checked exceptions.

Test: "lsof | grep network_st" while running "dumpsys tethering bpf" in a loop
Change-Id: I66c407454c2715bf41bf3a2e81bd582f9ea5a905
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index b17bfcf..4ba5130 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -766,17 +766,16 @@
     }
 
     private void dumpIpv6UpstreamRules(IndentingPrintWriter pw) {
-        final BpfMap<TetherUpstream6Key, Tether6Value> ipv6UpstreamMap = mDeps.getBpfUpstream6Map();
-        if (ipv6UpstreamMap == null) {
-            pw.println("No IPv6 upstream");
-            return;
-        }
-        try {
-            if (ipv6UpstreamMap.isEmpty()) {
+        try (BpfMap<TetherUpstream6Key, Tether6Value> map = mDeps.getBpfUpstream6Map()) {
+            if (map == null) {
+                pw.println("No IPv6 upstream");
+                return;
+            }
+            if (map.isEmpty()) {
                 pw.println("No IPv6 upstream rules");
                 return;
             }
-            ipv6UpstreamMap.forEach((k, v) -> pw.println(ipv6UpstreamRuletoString(k, v)));
+            map.forEach((k, v) -> pw.println(ipv6UpstreamRuletoString(k, v)));
         } catch (ErrnoException e) {
             pw.println("Error dumping IPv4 map: " + e);
         }
@@ -797,19 +796,18 @@
     }
 
     private void dumpIpv4ForwardingRules(IndentingPrintWriter pw) {
-        final BpfMap<Tether4Key, Tether4Value> ipv4UpstreamMap = mDeps.getBpfUpstream4Map();
-        if (ipv4UpstreamMap == null) {
-            pw.println("No IPv4 support");
-            return;
-        }
-        try {
-            if (ipv4UpstreamMap.isEmpty()) {
+        try (BpfMap<Tether4Key, Tether4Value> map = mDeps.getBpfUpstream4Map()) {
+            if (map == null) {
+                pw.println("No IPv4 support");
+                return;
+            }
+            if (map.isEmpty()) {
                 pw.println("No IPv4 rules");
                 return;
             }
             pw.println("[IPv4]: iif(iface) oif(iface) src nat dst");
             pw.increaseIndent();
-            ipv4UpstreamMap.forEach((k, v) -> pw.println(ipv4RuleToString(k, v)));
+            map.forEach((k, v) -> pw.println(ipv4RuleToString(k, v)));
         } catch (ErrnoException e) {
             pw.println("Error dumping IPv4 map: " + e);
         }
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfMap.java b/Tethering/src/com/android/networkstack/tethering/BpfMap.java
index 89caa8a..bc01dbd 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfMap.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfMap.java
@@ -218,7 +218,7 @@
     }
 
     @Override
-    public void close() throws Exception {
+    public void close() throws ErrnoException {
         closeMap(mMapFd);
     }