Use NetworkStatsService to get stats for apps

Move the native implementation of TrafficStats to NetworkStatsService
and apps need to get the NetworkStatsService binder interface from
system_server in order to get the network usage stats since boot. This
implementation can hide the detail of retrieving network traffic
information from apps and the NetworkStatsService can choose which
methoed it use to get the data depending on the kernel version of the
device.

Bug: 30950746
Test: CtsNetTestCases -t android.net.cts.TrafficStatsTest
Change-Id: I53bbefd19aa0b783b9b4b42ea4d76db3e9ec07a3
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 9180112..95e7f60 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -67,4 +67,13 @@
     /** Unregisters a callback on data usage. */
     void unregisterUsageRequest(in DataUsageRequest request);
 
+    /** Get the uid stats information since boot */
+    long getUidStats(int uid, int type);
+
+    /** Get the iface stats information since boot */
+    long getIfaceStats(String iface, int type);
+
+    /** Get the total network stats information since boot */
+    long getTotalStats(int type);
+
 }
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index d701550..196a3bc 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -505,7 +505,12 @@
     public static long getMobileTcpRxPackets() {
         long total = 0;
         for (String iface : getMobileIfaces()) {
-            final long stat = nativeGetIfaceStat(iface, TYPE_TCP_RX_PACKETS);
+            long stat = UNSUPPORTED;
+            try {
+                stat = getStatsService().getIfaceStats(iface, TYPE_TCP_RX_PACKETS);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
             if (stat != UNSUPPORTED) {
                 total += stat;
             }
@@ -517,7 +522,12 @@
     public static long getMobileTcpTxPackets() {
         long total = 0;
         for (String iface : getMobileIfaces()) {
-            final long stat = nativeGetIfaceStat(iface, TYPE_TCP_TX_PACKETS);
+            long stat = UNSUPPORTED;
+            try {
+                stat = getStatsService().getIfaceStats(iface, TYPE_TCP_TX_PACKETS);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
             if (stat != UNSUPPORTED) {
                 total += stat;
             }
@@ -527,46 +537,78 @@
 
     /** {@hide} */
     public static long getTxPackets(String iface) {
-        return nativeGetIfaceStat(iface, TYPE_TX_PACKETS);
+        try {
+            return getStatsService().getIfaceStats(iface, TYPE_TX_PACKETS);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /** {@hide} */
     public static long getRxPackets(String iface) {
-        return nativeGetIfaceStat(iface, TYPE_RX_PACKETS);
+        try {
+            return getStatsService().getIfaceStats(iface, TYPE_RX_PACKETS);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /** {@hide} */
     public static long getTxBytes(String iface) {
-        return nativeGetIfaceStat(iface, TYPE_TX_BYTES);
+        try {
+            return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /** {@hide} */
     public static long getRxBytes(String iface) {
-        return nativeGetIfaceStat(iface, TYPE_RX_BYTES);
+        try {
+            return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /** {@hide} */
     @TestApi
     public static long getLoopbackTxPackets() {
-        return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_TX_PACKETS);
+        try {
+            return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_PACKETS);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /** {@hide} */
     @TestApi
     public static long getLoopbackRxPackets() {
-        return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_RX_PACKETS);
+        try {
+            return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_PACKETS);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /** {@hide} */
     @TestApi
     public static long getLoopbackTxBytes() {
-        return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_TX_BYTES);
+        try {
+            return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_BYTES);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /** {@hide} */
     @TestApi
     public static long getLoopbackRxBytes() {
-        return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_RX_BYTES);
+        try {
+            return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_BYTES);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -579,7 +621,11 @@
      * return {@link #UNSUPPORTED} on devices where statistics aren't available.
      */
     public static long getTotalTxPackets() {
-        return nativeGetTotalStat(TYPE_TX_PACKETS);
+        try {
+            return getStatsService().getTotalStats(TYPE_TX_PACKETS);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -592,7 +638,11 @@
      * return {@link #UNSUPPORTED} on devices where statistics aren't available.
      */
     public static long getTotalRxPackets() {
-        return nativeGetTotalStat(TYPE_RX_PACKETS);
+        try {
+            return getStatsService().getTotalStats(TYPE_RX_PACKETS);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -605,7 +655,11 @@
      * return {@link #UNSUPPORTED} on devices where statistics aren't available.
      */
     public static long getTotalTxBytes() {
-        return nativeGetTotalStat(TYPE_TX_BYTES);
+        try {
+            return getStatsService().getTotalStats(TYPE_TX_BYTES);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -618,7 +672,11 @@
      * return {@link #UNSUPPORTED} on devices where statistics aren't available.
      */
     public static long getTotalRxBytes() {
-        return nativeGetTotalStat(TYPE_RX_BYTES);
+        try {
+            return getStatsService().getTotalStats(TYPE_RX_BYTES);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -644,7 +702,11 @@
         // unsupported value. The real filtering is done at the kernel level.
         final int callingUid = android.os.Process.myUid();
         if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
-            return nativeGetUidStat(uid, TYPE_TX_BYTES);
+            try {
+                return getStatsService().getUidStats(uid, TYPE_TX_BYTES);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
         } else {
             return UNSUPPORTED;
         }
@@ -673,7 +735,11 @@
         // unsupported value. The real filtering is done at the kernel level.
         final int callingUid = android.os.Process.myUid();
         if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
-            return nativeGetUidStat(uid, TYPE_RX_BYTES);
+            try {
+                return getStatsService().getUidStats(uid, TYPE_RX_BYTES);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
         } else {
             return UNSUPPORTED;
         }
@@ -702,7 +768,11 @@
         // unsupported value. The real filtering is done at the kernel level.
         final int callingUid = android.os.Process.myUid();
         if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
-            return nativeGetUidStat(uid, TYPE_TX_PACKETS);
+            try {
+                return getStatsService().getUidStats(uid, TYPE_TX_PACKETS);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
         } else {
             return UNSUPPORTED;
         }
@@ -731,7 +801,11 @@
         // unsupported value. The real filtering is done at the kernel level.
         final int callingUid = android.os.Process.myUid();
         if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
-            return nativeGetUidStat(uid, TYPE_RX_PACKETS);
+            try {
+                return getStatsService().getUidStats(uid, TYPE_RX_PACKETS);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
         } else {
             return UNSUPPORTED;
         }
@@ -859,8 +933,4 @@
     private static final int TYPE_TX_PACKETS = 3;
     private static final int TYPE_TCP_RX_PACKETS = 4;
     private static final int TYPE_TCP_TX_PACKETS = 5;
-
-    private static native long nativeGetTotalStat(int type);
-    private static native long nativeGetIfaceStat(String iface, int type);
-    private static native long nativeGetUidStat(int uid, int type);
 }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 336fee1..551d54a 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -96,7 +96,6 @@
         "android_os_VintfRuntimeInfo.cpp",
         "android_net_LocalSocketImpl.cpp",
         "android_net_NetUtils.cpp",
-        "android_net_TrafficStats.cpp",
         "android_nio_utils.cpp",
         "android_util_AssetManager.cpp",
         "android_util_Binder.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 9059862..5382640 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -173,7 +173,6 @@
 extern int register_android_os_SharedMemory(JNIEnv* env);
 extern int register_android_net_LocalSocketImpl(JNIEnv* env);
 extern int register_android_net_NetworkUtils(JNIEnv* env);
-extern int register_android_net_TrafficStats(JNIEnv* env);
 extern int register_android_text_AndroidCharacter(JNIEnv *env);
 extern int register_android_text_StaticLayout(JNIEnv *env);
 extern int register_android_text_AndroidBidi(JNIEnv *env);
@@ -1419,7 +1418,6 @@
     REG_JNI(register_android_os_UEventObserver),
     REG_JNI(register_android_net_LocalSocketImpl),
     REG_JNI(register_android_net_NetworkUtils),
-    REG_JNI(register_android_net_TrafficStats),
     REG_JNI(register_android_os_MemoryFile),
     REG_JNI(register_android_os_SharedMemory),
     REG_JNI(register_com_android_internal_os_ClassLoaderFactory),
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 3af5265..db61ef5 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -873,6 +873,21 @@
         }
     }
 
+    @Override
+    public long getUidStats(int uid, int type) {
+        return nativeGetUidStat(uid, type);
+    }
+
+    @Override
+    public long getIfaceStats(String iface, int type) {
+        return nativeGetIfaceStat(iface, type);
+    }
+
+    @Override
+    public long getTotalStats(int type) {
+        return nativeGetTotalStat(type);
+    }
+
     /**
      * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
      * reflect current {@link #mPersistThreshold} value. Always defers to
@@ -1626,4 +1641,15 @@
             return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def);
         }
     }
+
+    private static int TYPE_RX_BYTES;
+    private static int TYPE_RX_PACKETS;
+    private static int TYPE_TX_BYTES;
+    private static int TYPE_TX_PACKETS;
+    private static int TYPE_TCP_RX_PACKETS;
+    private static int TYPE_TCP_TX_PACKETS;
+
+    private static native long nativeGetTotalStat(int type);
+    private static native long nativeGetIfaceStat(String iface, int type);
+    private static native long nativeGetUidStat(int uid, int type);
 }
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 27acaee..04fd3e3 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -33,6 +33,7 @@
         "com_android_server_location_ContextHubService.cpp",
         "com_android_server_location_GnssLocationProvider.cpp",
         "com_android_server_locksettings_SyntheticPasswordManager.cpp",
+        "com_android_server_net_NetworkStatsService.cpp",
         "com_android_server_power_PowerManagerService.cpp",
         "com_android_server_SerialService.cpp",
         "com_android_server_storage_AppFuseBridge.cpp",
diff --git a/core/jni/android_net_TrafficStats.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
similarity index 79%
rename from core/jni/android_net_TrafficStats.cpp
rename to services/core/jni/com_android_server_net_NetworkStatsService.cpp
index d0c237d..8de24e5 100644
--- a/core/jni/android_net_TrafficStats.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "TrafficStats"
+#define LOG_TAG "NetworkStatsNative"
 
 #include <dirent.h>
 #include <errno.h>
@@ -191,8 +191,24 @@
     {"nativeGetUidStat", "(II)J", (void*) getUidStat},
 };
 
-int register_android_net_TrafficStats(JNIEnv* env) {
-    return RegisterMethodsOrDie(env, "android/net/TrafficStats", gMethods, NELEM(gMethods));
+int register_android_server_net_NetworkStatsService(JNIEnv* env) {
+    jclass netStatsService = env->FindClass("com/android/server/net/NetworkStatsService");
+    jfieldID rxBytesId = env->GetStaticFieldID(netStatsService, "TYPE_RX_BYTES", "I");
+    jfieldID rxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_RX_PACKETS", "I");
+    jfieldID txBytesId = env->GetStaticFieldID(netStatsService, "TYPE_TX_BYTES", "I");
+    jfieldID txPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TX_PACKETS", "I");
+    jfieldID tcpRxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TCP_RX_PACKETS", "I");
+    jfieldID tcpTxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TCP_TX_PACKETS", "I");
+
+    env->SetStaticIntField(netStatsService, rxBytesId, RX_BYTES);
+    env->SetStaticIntField(netStatsService, rxPacketsId, RX_PACKETS);
+    env->SetStaticIntField(netStatsService, txBytesId, TX_BYTES);
+    env->SetStaticIntField(netStatsService, txPacketsId, TX_PACKETS);
+    env->SetStaticIntField(netStatsService, tcpRxPacketsId, TCP_RX_PACKETS);
+    env->SetStaticIntField(netStatsService, tcpTxPacketsId, TCP_TX_PACKETS);
+
+    return jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsService", gMethods,
+                                    NELEM(gMethods));
 }
 
 }
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index e8ef168..8dfbbf3 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -52,6 +52,7 @@
 int register_android_server_SyntheticPasswordManager(JNIEnv* env);
 int register_android_server_GraphicsStatsService(JNIEnv* env);
 int register_android_hardware_display_DisplayViewport(JNIEnv* env);
+int register_android_server_net_NetworkStatsService(JNIEnv* env);
 };
 
 using namespace android;
@@ -98,6 +99,7 @@
     register_android_server_SyntheticPasswordManager(env);
     register_android_server_GraphicsStatsService(env);
     register_android_hardware_display_DisplayViewport(env);
+    register_android_server_net_NetworkStatsService(env);
 
     return JNI_VERSION_1_4;
 }