Merge "Merge Android 12L"
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index b65c0ce..751a1e2 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -28,7 +28,6 @@
     method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setRequireVpnForUids(boolean, @NonNull java.util.Collection<android.util.Range<java.lang.Integer>>);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void startCaptivePortalApp(@NonNull android.net.Network);
-    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void swapActiveStatsMap();
     method public void systemReady();
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void updateFirewallRule(int, int, boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void updateMeteredNetworkAllowList(int, boolean);
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index e8e1efa..8651f34 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -5818,27 +5818,4 @@
             throw e.rethrowFromSystemServer();
         }
     }
-
-    /**
-     * Request to change the current active network stats map.
-     * STOPSHIP: Remove this API before T sdk finalized, this API is temporary added for the
-     * NetworkStatsFactory which is platform code but will be moved into connectivity (tethering)
-     * mainline module.
-     *
-     * @throws IllegalStateException if swapping active stats map failed.
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    @RequiresPermission(anyOf = {
-            android.Manifest.permission.NETWORK_SETTINGS,
-            android.Manifest.permission.NETWORK_STACK,
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
-    })
-    public void swapActiveStatsMap() {
-        try {
-            mService.swapActiveStatsMap();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
 }
diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl
index 23a3850..1e1f653 100644
--- a/framework/src/android/net/IConnectivityManager.aidl
+++ b/framework/src/android/net/IConnectivityManager.aidl
@@ -245,6 +245,4 @@
     void setFirewallChainEnabled(int chain, boolean enable);
 
     void replaceFirewallChain(int chain, in int[] uids);
-
-    void swapActiveStatsMap();
 }
diff --git a/netd/BpfHandler.cpp b/netd/BpfHandler.cpp
index 1e47ea3..f3dfb57 100644
--- a/netd/BpfHandler.cpp
+++ b/netd/BpfHandler.cpp
@@ -146,20 +146,32 @@
     // The socket destroy listener only monitors on the group {INET_TCP, INET_UDP, INET6_TCP,
     // INET6_UDP}. Tagging listener unsupported socket causes that the tag can't be removed from
     // tag map automatically. Eventually, the tag map may run out of space because of dead tag
-    // entries.
-    // See TrafficController::makeSkDestroyListener in
+    // entries. Note that although tagSocket() of net client has already denied the family which
+    // is neither AF_INET nor AF_INET6, the family validation is still added here just in case.
+    // See tagSocket in system/netd/client/NetdClient.cpp and
+    // TrafficController::makeSkDestroyListener in
     // packages/modules/Connectivity/service/native/TrafficController.cpp
     // TODO: remove this once the socket destroy listener can detect more types of socket destroy.
-    int socketProto;
-    socklen_t intSize = sizeof(socketProto);
-    if (getsockopt(sockFd, SOL_SOCKET, SO_PROTOCOL, &socketProto, &intSize)) {
-        ALOGE("Failed to getsockopt: %s, fd: %d", strerror(errno), sockFd);
+    int socketFamily;
+    socklen_t familyLen = sizeof(socketFamily);
+    if (getsockopt(sockFd, SOL_SOCKET, SO_DOMAIN, &socketFamily, &familyLen)) {
+        ALOGE("Failed to getsockopt SO_DOMAIN: %s, fd: %d", strerror(errno), sockFd);
         return -errno;
-    } else {
-        if (socketProto != IPPROTO_UDP && socketProto != IPPROTO_TCP) {
-            ALOGE("Unsupported protocol: %d", socketProto);
-            return -EPROTONOSUPPORT;
-        }
+    }
+    if (socketFamily != AF_INET && socketFamily != AF_INET6) {
+        ALOGE("Unsupported family: %d", socketFamily);
+        return -EAFNOSUPPORT;
+    }
+
+    int socketProto;
+    socklen_t protoLen = sizeof(socketProto);
+    if (getsockopt(sockFd, SOL_SOCKET, SO_PROTOCOL, &socketProto, &protoLen)) {
+        ALOGE("Failed to getsockopt SO_PROTOCOL: %s, fd: %d", strerror(errno), sockFd);
+        return -errno;
+    }
+    if (socketProto != IPPROTO_UDP && socketProto != IPPROTO_TCP) {
+        ALOGE("Unsupported protocol: %d", socketProto);
+        return -EPROTONOSUPPORT;
     }
 
     uint64_t sock_cookie = getSocketCookie(sockFd);
diff --git a/netd/BpfHandlerTest.cpp b/netd/BpfHandlerTest.cpp
index 66a2f80..cd6b565 100644
--- a/netd/BpfHandlerTest.cpp
+++ b/netd/BpfHandlerTest.cpp
@@ -188,11 +188,17 @@
     expectMapEmpty(mFakeCookieTagMap);
 }
 
+TEST_F(BpfHandlerTest, TestTagSocketWithUnsupportedFamily) {
+    int packetSocket = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+    EXPECT_LE(0, packetSocket);
+    EXPECT_NE(NONEXISTENT_COOKIE, getSocketCookie(packetSocket));
+    EXPECT_EQ(-EAFNOSUPPORT, mBh.tagSocket(packetSocket, TEST_TAG, TEST_UID, TEST_UID));
+}
+
 TEST_F(BpfHandlerTest, TestTagSocketWithUnsupportedProtocol) {
     int rawSocket = socket(AF_INET, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_RAW);
     EXPECT_LE(0, rawSocket);
-    uint64_t sockCookie = getSocketCookie(rawSocket);
-    EXPECT_NE(NONEXISTENT_COOKIE, sockCookie);
+    EXPECT_NE(NONEXISTENT_COOKIE, getSocketCookie(rawSocket));
     EXPECT_EQ(-EPROTONOSUPPORT, mBh.tagSocket(rawSocket, TEST_TAG, TEST_UID, TEST_UID));
 }
 
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index 71ddd11..4517b5c 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -18,6 +18,7 @@
 #include <arpa/inet.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <linux/if_tun.h>
 #include <linux/ioctl.h>
 #include <log/log.h>
@@ -27,7 +28,11 @@
 #include <sys/wait.h>
 #include <string>
 
+#include <bpf/BpfMap.h>
+#include <bpf/BpfUtils.h>
+#include <bpf_shared.h>
 #include <netjniutils/netjniutils.h>
+#include <private/android_filesystem_config.h>
 
 #include "libclat/bpfhelper.h"
 #include "libclat/clatutils.h"
@@ -473,6 +478,72 @@
     stopClatdProcess(pid);
 }
 
+static jlong com_android_server_connectivity_ClatCoordinator_tagSocketAsClat(
+        JNIEnv* env, jobject clazz, jobject sockJavaFd) {
+    int sockFd = netjniutils::GetNativeFileDescriptor(env, sockJavaFd);
+    if (sockFd < 0) {
+        jniThrowExceptionFmt(env, "java/io/IOException", "Invalid socket file descriptor");
+        return -1;
+    }
+
+    uint64_t sock_cookie = bpf::getSocketCookie(sockFd);
+    if (sock_cookie == bpf::NONEXISTENT_COOKIE) {
+        throwIOException(env, "get socket cookie failed", errno);
+        return -1;
+    }
+
+    bpf::BpfMap<uint64_t, UidTagValue> cookieTagMap;
+    auto res = cookieTagMap.init(COOKIE_TAG_MAP_PATH);
+    if (!res.ok()) {
+        throwIOException(env, "failed to init the cookieTagMap", res.error().code());
+        return -1;
+    }
+
+    // Tag raw socket with uid AID_CLAT and set tag as zero because tag is unused in bpf
+    // program for counting data usage in netd.c. Tagging socket is used to avoid counting
+    // duplicated clat traffic in bpf stat.
+    UidTagValue newKey = {.uid = (uint32_t)AID_CLAT, .tag = 0 /* unused */};
+    res = cookieTagMap.writeValue(sock_cookie, newKey, BPF_ANY);
+    if (!res.ok()) {
+        jniThrowExceptionFmt(env, "java/io/IOException", "Failed to tag the socket: %s, fd: %d",
+                             strerror(res.error().code()), cookieTagMap.getMap().get());
+        return -1;
+    }
+
+    ALOGI("tag uid AID_CLAT to socket fd %d, cookie %" PRIu64 "", sockFd, sock_cookie);
+    return static_cast<jlong>(sock_cookie);
+}
+
+static void com_android_server_connectivity_ClatCoordinator_untagSocket(JNIEnv* env, jobject clazz,
+                                                                        jlong cookie) {
+    uint64_t sock_cookie = static_cast<uint64_t>(cookie);
+    if (sock_cookie == bpf::NONEXISTENT_COOKIE) {
+        jniThrowExceptionFmt(env, "java/io/IOException", "Invalid socket cookie");
+        return;
+    }
+
+    // The reason that deleting entry from cookie tag map directly is that the tag socket destroy
+    // listener only monitors on group INET_TCP, INET_UDP, INET6_TCP, INET6_UDP. The other socket
+    // types, ex: raw, are not able to be removed automatically by the listener.
+    // See TrafficController::makeSkDestroyListener.
+    bpf::BpfMap<uint64_t, UidTagValue> cookieTagMap;
+    auto res = cookieTagMap.init(COOKIE_TAG_MAP_PATH);
+    if (!res.ok()) {
+        throwIOException(env, "failed to init the cookieTagMap", res.error().code());
+        return;
+    }
+
+    res = cookieTagMap.deleteValue(sock_cookie);
+    if (!res.ok()) {
+        jniThrowExceptionFmt(env, "java/io/IOException", "Failed to untag the socket: %s",
+                             strerror(res.error().code()));
+        return;
+    }
+
+    ALOGI("untag socket cookie %" PRIu64 "", sock_cookie);
+    return;
+}
+
 /*
  * JNI registration.
  */
@@ -502,6 +573,10 @@
         {"native_stopClatd",
          "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V",
          (void*)com_android_server_connectivity_ClatCoordinator_stopClatd},
+        {"native_tagSocketAsClat", "(Ljava/io/FileDescriptor;)J",
+         (void*)com_android_server_connectivity_ClatCoordinator_tagSocketAsClat},
+        {"native_untagSocket", "(J)V",
+         (void*)com_android_server_connectivity_ClatCoordinator_untagSocket},
 };
 
 int register_com_android_server_connectivity_ClatCoordinator(JNIEnv* env) {
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index c977391..c006bc6 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -54,6 +54,13 @@
         sInitialized = true;
     }
 
+    /** Constructor used after T that doesn't need to use netd anymore. */
+    public BpfNetMaps() {
+        this(null);
+
+        if (USE_NETD) throw new IllegalArgumentException("BpfNetMaps need to use netd before T");
+    }
+
     public BpfNetMaps(INetd netd) {
         ensureInitialized();
         mNetd = netd;
@@ -211,15 +218,10 @@
     /**
      * Request netd to change the current active network stats map.
      *
-     * @throws RemoteException when netd has crashed.
      * @throws ServiceSpecificException in case of failure, with an error code indicating the
      *                                  cause of the failure.
      */
-    public void swapActiveStatsMap() throws RemoteException {
-        if (USE_NETD) {
-            mNetd.trafficSwapActiveStatsMap();
-            return;
-        }
+    public void swapActiveStatsMap() {
         final int err = native_swapActiveStatsMap();
         maybeThrow(err, "Unable to swap active stats map");
     }
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index e0bf223..dd92a18 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -11132,14 +11132,4 @@
             throw new IllegalStateException(e);
         }
     }
-
-    @Override
-    public void swapActiveStatsMap() {
-        enforceNetworkStackOrSettingsPermission();
-        try {
-            mBpfNetMaps.swapActiveStatsMap();
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
 }
diff --git a/service/src/com/android/server/connectivity/ClatCoordinator.java b/service/src/com/android/server/connectivity/ClatCoordinator.java
index c57983b..c1a8195 100644
--- a/service/src/com/android/server/connectivity/ClatCoordinator.java
+++ b/service/src/com/android/server/connectivity/ClatCoordinator.java
@@ -67,6 +67,7 @@
 
     private static final int INVALID_IFINDEX = 0;
     private static final int INVALID_PID = 0;
+    private static final long INVALID_COOKIE = 0;
 
     @NonNull
     private final INetd mNetd;
@@ -81,6 +82,7 @@
     @Nullable
     private String mXlatLocalAddress6 = null;
     private int mPid = INVALID_PID;
+    private long mCookie = INVALID_COOKIE;
 
     @VisibleForTesting
     abstract static class Dependencies {
@@ -185,6 +187,20 @@
                 throws IOException {
             native_stopClatd(iface, pfx96, v4, v6, pid);
         }
+
+        /**
+         * Tag socket as clat.
+         */
+        public long tagSocketAsClat(@NonNull FileDescriptor sock) throws IOException {
+            return native_tagSocketAsClat(sock);
+        }
+
+        /**
+         * Untag socket.
+         */
+        public void untagSocket(long cookie) throws IOException {
+            native_untagSocket(cookie);
+        }
     }
 
     @VisibleForTesting
@@ -335,6 +351,17 @@
             throw new IOException("add anycast sockopt failed: " + e);
         }
 
+        // Tag socket as AID_CLAT to avoid duplicated CLAT data usage accounting.
+        long cookie;
+        try {
+            cookie = mDeps.tagSocketAsClat(writeSock6.getFileDescriptor());
+        } catch (IOException e) {
+            tunFd.close();
+            readSock6.close();
+            writeSock6.close();
+            throw new IOException("tag raw socket failed: " + e);
+        }
+
         // Update our packet socket filter to reflect the new 464xlat IP address.
         try {
             mDeps.configurePacketSocket(readSock6.getFileDescriptor(), v6, ifaceIndex);
@@ -353,7 +380,9 @@
             mNat64Prefix = pfx96;
             mXlatLocalAddress4 = v4;
             mXlatLocalAddress6 = v6;
+            mCookie = cookie;
         } catch (IOException e) {
+            mDeps.untagSocket(cookie);
             throw new IOException("Error start clatd on " + iface + ": " + e);
         } finally {
             tunFd.close();
@@ -374,7 +403,7 @@
         Log.i(TAG, "Stopping clatd pid=" + mPid + " on " + mIface);
 
         mDeps.stopClatd(mIface, mNat64Prefix, mXlatLocalAddress4, mXlatLocalAddress6, mPid);
-        // TODO: remove setIptablesDropRule
+        mDeps.untagSocket(mCookie);
 
         Log.i(TAG, "clatd on " + mIface + " stopped");
 
@@ -383,6 +412,7 @@
         mXlatLocalAddress4 = null;
         mXlatLocalAddress6 = null;
         mPid = INVALID_PID;
+        mCookie = INVALID_COOKIE;
     }
 
     private static native String native_selectIpv4Address(String v4addr, int prefixlen)
@@ -403,4 +433,6 @@
             throws IOException;
     private static native void native_stopClatd(String iface, String pfx96, String v4, String v6,
             int pid) throws IOException;
+    private static native long native_tagSocketAsClat(FileDescriptor sock) throws IOException;
+    private static native void native_untagSocket(long cookie) throws IOException;
 }
diff --git a/tests/unit/java/com/android/server/BpfNetMapsTest.java b/tests/unit/java/com/android/server/BpfNetMapsTest.java
index 2959ac9..f07a10d 100644
--- a/tests/unit/java/com/android/server/BpfNetMapsTest.java
+++ b/tests/unit/java/com/android/server/BpfNetMapsTest.java
@@ -62,8 +62,6 @@
         verify(mNetd).firewallAddUidInterfaceRules(IFNAME, TEST_UIDS);
         mBpfNetMaps.removeUidInterfaceRules(TEST_UIDS);
         verify(mNetd).firewallRemoveUidInterfaceRules(TEST_UIDS);
-        mBpfNetMaps.swapActiveStatsMap();
-        verify(mNetd).trafficSwapActiveStatsMap();
         mBpfNetMaps.setNetPermForUids(PERMISSION_INTERNET, TEST_UIDS);
         verify(mNetd).trafficSetNetPermForUids(PERMISSION_INTERNET, TEST_UIDS);
     }
diff --git a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
index 84e02ce..8a2cfc2 100644
--- a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
@@ -26,13 +26,10 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.argThat;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.never;
 
 import android.annotation.NonNull;
 import android.net.INetd;
@@ -82,6 +79,7 @@
     private static final int TUN_FD = 534;
     private static final int RAW_SOCK_FD = 535;
     private static final int PACKET_SOCK_FD = 536;
+    private static final long RAW_SOCK_COOKIE = 27149;
     private static final ParcelFileDescriptor TUN_PFD = new ParcelFileDescriptor(
             new FileDescriptor());
     private static final ParcelFileDescriptor RAW_SOCK_PFD = new ParcelFileDescriptor(
@@ -258,12 +256,35 @@
         /**
          * Stop clatd.
          */
+        @Override
         public void stopClatd(@NonNull String iface, @NonNull String pfx96, @NonNull String v4,
                 @NonNull String v6, int pid) throws IOException {
             if (pid == -1) {
                 fail("unsupported arg: " + pid);
             }
         }
+
+        /**
+         * Tag socket as clat.
+         */
+        @Override
+        public long tagSocketAsClat(@NonNull FileDescriptor sock) throws IOException {
+            if (Objects.equals(RAW_SOCK_PFD.getFileDescriptor(), sock)) {
+                return RAW_SOCK_COOKIE;
+            }
+            fail("unsupported arg: " + sock);
+            return 0;
+        }
+
+        /**
+         * Untag socket.
+         */
+        @Override
+        public void untagSocket(long cookie) throws IOException {
+            if (cookie != RAW_SOCK_COOKIE) {
+                fail("unsupported arg: " + cookie);
+            }
+        }
     };
 
     @NonNull
@@ -326,6 +347,8 @@
         inOrder.verify(mDeps).addAnycastSetsockopt(
                 argThat(fd -> Objects.equals(RAW_SOCK_PFD.getFileDescriptor(), fd)),
                 eq(XLAT_LOCAL_IPV6ADDR_STRING), eq(BASE_IFINDEX));
+        inOrder.verify(mDeps).tagSocketAsClat(
+                argThat(fd -> Objects.equals(RAW_SOCK_PFD.getFileDescriptor(), fd)));
         inOrder.verify(mDeps).configurePacketSocket(
                 argThat(fd -> Objects.equals(PACKET_SOCK_PFD.getFileDescriptor(), fd)),
                 eq(XLAT_LOCAL_IPV6ADDR_STRING), eq(BASE_IFINDEX));
@@ -348,13 +371,12 @@
         coordinator.clatStop();
         inOrder.verify(mDeps).stopClatd(eq(BASE_IFACE), eq(NAT64_PREFIX_STRING),
                 eq(XLAT_LOCAL_IPV4ADDR_STRING), eq(XLAT_LOCAL_IPV6ADDR_STRING), eq(CLATD_PID));
+        inOrder.verify(mDeps).untagSocket(eq(RAW_SOCK_COOKIE));
         inOrder.verifyNoMoreInteractions();
 
         // [4] Expect an IO exception while stopping a clatd that doesn't exist.
         assertThrows("java.io.IOException: Clatd has not started", IOException.class,
                 () -> coordinator.clatStop());
-        inOrder.verify(mDeps, never()).stopClatd(anyString(), anyString(), anyString(),
-                anyString(), anyInt());
         inOrder.verifyNoMoreInteractions();
     }
 
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
index 6872f80..79744b1 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
@@ -32,12 +32,9 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doReturn;
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.net.ConnectivityManager;
 import android.net.NetworkStats;
 import android.net.TrafficStats;
 import android.net.UnderlyingNetworkInfo;
@@ -77,7 +74,6 @@
     private File mTestProc;
     private NetworkStatsFactory mFactory;
     @Mock private Context mContext;
-    @Mock private ConnectivityManager mCm;
 
     @Before
     public void setUp() throws Exception {
@@ -88,9 +84,6 @@
         // applications. So in order to have a test support native library, the native code
         // related to networkStatsFactory is compiled to a minimal native library and loaded here.
         System.loadLibrary("networkstatsfactorytestjni");
-        doReturn(Context.CONNECTIVITY_SERVICE).when(mContext).getSystemServiceName(
-                eq(ConnectivityManager.class));
-        doReturn(mCm).when(mContext).getSystemService(eq(Context.CONNECTIVITY_SERVICE));
         mFactory = new NetworkStatsFactory(mContext, mTestProc, false);
         mFactory.updateUnderlyingNetworkInfos(new UnderlyingNetworkInfo[0]);
     }