summaryrefslogtreecommitdiff
path: root/framework-t/src/android/net/TrafficStats.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework-t/src/android/net/TrafficStats.java')
-rw-r--r--framework-t/src/android/net/TrafficStats.java1148
1 files changed, 1148 insertions, 0 deletions
diff --git a/framework-t/src/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java
new file mode 100644
index 0000000000..dc4ac552a4
--- /dev/null
+++ b/framework-t/src/android/net/TrafficStats.java
@@ -0,0 +1,1148 @@
+/*
+ * Copyright (C) 2007 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 android.net;
+
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.app.DownloadManager;
+import android.app.backup.BackupManager;
+import android.app.usage.NetworkStatsManager;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.os.Binder;
+import android.os.Build;
+import android.os.RemoteException;
+import android.os.StrictMode;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.Socket;
+import java.net.SocketException;
+
+/**
+ * Class that provides network traffic statistics. These statistics include
+ * bytes transmitted and received and network packets transmitted and received,
+ * over all interfaces, over the mobile interface, and on a per-UID basis.
+ * <p>
+ * These statistics may not be available on all platforms. If the statistics are
+ * not supported by this device, {@link #UNSUPPORTED} will be returned.
+ * <p>
+ * Note that the statistics returned by this class reset and start from zero
+ * after every reboot. To access more robust historical network statistics data,
+ * use {@link NetworkStatsManager} instead.
+ */
+public class TrafficStats {
+ static {
+ System.loadLibrary("framework-connectivity-tiramisu-jni");
+ }
+
+ private static final String TAG = TrafficStats.class.getSimpleName();
+ /**
+ * The return value to indicate that the device does not support the statistic.
+ */
+ public final static int UNSUPPORTED = -1;
+
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
+ public static final long KB_IN_BYTES = 1024;
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
+ public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
+ public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
+ public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
+ public static final long PB_IN_BYTES = TB_IN_BYTES * 1024;
+
+ /**
+ * Special UID value used when collecting {@link NetworkStatsHistory} for
+ * removed applications.
+ *
+ * @hide
+ */
+ public static final int UID_REMOVED = -4;
+
+ /**
+ * Special UID value used when collecting {@link NetworkStatsHistory} for
+ * tethering traffic.
+ *
+ * @hide
+ */
+ public static final int UID_TETHERING = NetworkStats.UID_TETHERING;
+
+ /**
+ * Tag values in this range are reserved for the network stack. The network stack is
+ * running as UID {@link android.os.Process.NETWORK_STACK_UID} when in the mainline
+ * module separate process, and as the system UID otherwise.
+ */
+ /** @hide */
+ @SystemApi
+ public static final int TAG_NETWORK_STACK_RANGE_START = 0xFFFFFD00;
+ /** @hide */
+ @SystemApi
+ public static final int TAG_NETWORK_STACK_RANGE_END = 0xFFFFFEFF;
+
+ /**
+ * Tags between 0xFFFFFF00 and 0xFFFFFFFF are reserved and used internally by system services
+ * like DownloadManager when performing traffic on behalf of an application.
+ */
+ // Please note there is no enforcement of these constants, so do not rely on them to
+ // determine that the caller is a system caller.
+ /** @hide */
+ @SystemApi
+ public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = 0xFFFFFF00;
+ /** @hide */
+ @SystemApi
+ public static final int TAG_SYSTEM_IMPERSONATION_RANGE_END = 0xFFFFFF0F;
+
+ /**
+ * Tag values between these ranges are reserved for the network stack to do traffic
+ * on behalf of applications. It is a subrange of the range above.
+ */
+ /** @hide */
+ @SystemApi
+ public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_START = 0xFFFFFF80;
+ /** @hide */
+ @SystemApi
+ public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_END = 0xFFFFFF8F;
+
+ /**
+ * Default tag value for {@link DownloadManager} traffic.
+ *
+ * @hide
+ */
+ public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFFFF01;
+
+ /**
+ * Default tag value for {@link MediaPlayer} traffic.
+ *
+ * @hide
+ */
+ public static final int TAG_SYSTEM_MEDIA = 0xFFFFFF02;
+
+ /**
+ * Default tag value for {@link BackupManager} backup traffic; that is,
+ * traffic from the device to the storage backend.
+ *
+ * @hide
+ */
+ public static final int TAG_SYSTEM_BACKUP = 0xFFFFFF03;
+
+ /**
+ * Default tag value for {@link BackupManager} restore traffic; that is,
+ * app data retrieved from the storage backend at install time.
+ *
+ * @hide
+ */
+ public static final int TAG_SYSTEM_RESTORE = 0xFFFFFF04;
+
+ /**
+ * Default tag value for code (typically APKs) downloaded by an app store on
+ * behalf of the app, such as updates.
+ *
+ * @hide
+ */
+ public static final int TAG_SYSTEM_APP = 0xFFFFFF05;
+
+ // TODO : remove this constant when Wifi code is updated
+ /** @hide */
+ public static final int TAG_SYSTEM_PROBE = 0xFFFFFF42;
+
+ private static INetworkStatsService sStatsService;
+
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
+ private synchronized static INetworkStatsService getStatsService() {
+ if (sStatsService == null) {
+ throw new IllegalStateException("TrafficStats not initialized, uid="
+ + Binder.getCallingUid());
+ }
+ return sStatsService;
+ }
+
+ /**
+ * Snapshot of {@link NetworkStats} when the currently active profiling
+ * session started, or {@code null} if no session active.
+ *
+ * @see #startDataProfiling(Context)
+ * @see #stopDataProfiling(Context)
+ */
+ private static NetworkStats sActiveProfilingStart;
+
+ private static Object sProfilingLock = new Object();
+
+ private static final String LOOPBACK_IFACE = "lo";
+
+ /**
+ * Initialization {@link TrafficStats} with the context, to
+ * allow {@link TrafficStats} to fetch the needed binder.
+ *
+ * @param context a long-lived context, such as the application context or system
+ * server context.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @SuppressLint("VisiblySynchronized")
+ public static synchronized void init(@NonNull final Context context) {
+ if (sStatsService != null) {
+ throw new IllegalStateException("TrafficStats is already initialized, uid="
+ + Binder.getCallingUid());
+ }
+ final NetworkStatsManager statsManager =
+ context.getSystemService(NetworkStatsManager.class);
+ if (statsManager == null) {
+ // TODO: Currently Process.isSupplemental is not working yet, because it depends on
+ // process to run in a certain UID range, which is not true for now. Change this
+ // to Log.wtf once Process.isSupplemental is ready.
+ Log.e(TAG, "TrafficStats not initialized, uid=" + Binder.getCallingUid());
+ return;
+ }
+ sStatsService = statsManager.getBinder();
+ }
+
+ /**
+ * Attach the socket tagger implementation to the current process, to
+ * get notified when a socket's {@link FileDescriptor} is assigned to
+ * a thread. See {@link SocketTagger#set(SocketTagger)}.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static void attachSocketTagger() {
+ dalvik.system.SocketTagger.set(new SocketTagger());
+ }
+
+ private static class SocketTagger extends dalvik.system.SocketTagger {
+
+ // TODO: set to false
+ private static final boolean LOGD = true;
+
+ SocketTagger() {
+ }
+
+ @Override
+ public void tag(FileDescriptor fd) throws SocketException {
+ final UidTag tagInfo = sThreadUidTag.get();
+ if (LOGD) {
+ Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
+ + Integer.toHexString(tagInfo.tag) + ", statsUid=" + tagInfo.uid);
+ }
+ if (tagInfo.tag == -1) {
+ StrictMode.noteUntaggedSocket();
+ }
+
+ if (tagInfo.tag == -1 && tagInfo.uid == -1) return;
+ final int errno = native_tagSocketFd(fd, tagInfo.tag, tagInfo.uid);
+ if (errno < 0) {
+ Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
+ + tagInfo.tag + ", "
+ + tagInfo.uid + ") failed with errno" + errno);
+ }
+ }
+
+ @Override
+ public void untag(FileDescriptor fd) throws SocketException {
+ if (LOGD) {
+ Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
+ }
+
+ final UidTag tagInfo = sThreadUidTag.get();
+ if (tagInfo.tag == -1 && tagInfo.uid == -1) return;
+
+ final int errno = native_untagSocketFd(fd);
+ if (errno < 0) {
+ Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
+ }
+ }
+ }
+
+ private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
+ private static native int native_untagSocketFd(FileDescriptor fd);
+
+ private static class UidTag {
+ public int tag = -1;
+ public int uid = -1;
+ }
+
+ private static ThreadLocal<UidTag> sThreadUidTag = new ThreadLocal<UidTag>() {
+ @Override
+ protected UidTag initialValue() {
+ return new UidTag();
+ }
+ };
+
+ /**
+ * Set active tag to use when accounting {@link Socket} traffic originating
+ * from the current thread. Only one active tag per thread is supported.
+ * <p>
+ * Changes only take effect during subsequent calls to
+ * {@link #tagSocket(Socket)}.
+ * <p>
+ * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
+ * used internally by system services like {@link DownloadManager} when
+ * performing traffic on behalf of an application.
+ *
+ * @see #clearThreadStatsTag()
+ */
+ public static void setThreadStatsTag(int tag) {
+ getAndSetThreadStatsTag(tag);
+ }
+
+ /**
+ * Set active tag to use when accounting {@link Socket} traffic originating
+ * from the current thread. Only one active tag per thread is supported.
+ * <p>
+ * Changes only take effect during subsequent calls to
+ * {@link #tagSocket(Socket)}.
+ * <p>
+ * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
+ * used internally by system services like {@link DownloadManager} when
+ * performing traffic on behalf of an application.
+ *
+ * @return the current tag for the calling thread, which can be used to
+ * restore any existing values after a nested operation is finished
+ */
+ public static int getAndSetThreadStatsTag(int tag) {
+ final int old = sThreadUidTag.get().tag;
+ sThreadUidTag.get().tag = tag;
+ return old;
+ }
+
+ /**
+ * Set active tag to use when accounting {@link Socket} traffic originating
+ * from the current thread. The tag used internally is well-defined to
+ * distinguish all backup-related traffic.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static void setThreadStatsTagBackup() {
+ setThreadStatsTag(TAG_SYSTEM_BACKUP);
+ }
+
+ /**
+ * Set active tag to use when accounting {@link Socket} traffic originating
+ * from the current thread. The tag used internally is well-defined to
+ * distinguish all restore-related traffic.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static void setThreadStatsTagRestore() {
+ setThreadStatsTag(TAG_SYSTEM_RESTORE);
+ }
+
+ /**
+ * Set active tag to use when accounting {@link Socket} traffic originating
+ * from the current thread. The tag used internally is well-defined to
+ * distinguish all code (typically APKs) downloaded by an app store on
+ * behalf of the app, such as updates.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static void setThreadStatsTagApp() {
+ setThreadStatsTag(TAG_SYSTEM_APP);
+ }
+
+ /**
+ * Set active tag to use when accounting {@link Socket} traffic originating
+ * from the current thread. The tag used internally is well-defined to
+ * distinguish all download provider traffic.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static void setThreadStatsTagDownload() {
+ setThreadStatsTag(TAG_SYSTEM_DOWNLOAD);
+ }
+
+ /**
+ * Get the active tag used when accounting {@link Socket} traffic originating
+ * from the current thread. Only one active tag per thread is supported.
+ * {@link #tagSocket(Socket)}.
+ *
+ * @see #setThreadStatsTag(int)
+ */
+ public static int getThreadStatsTag() {
+ return sThreadUidTag.get().tag;
+ }
+
+ /**
+ * Clear any active tag set to account {@link Socket} traffic originating
+ * from the current thread.
+ *
+ * @see #setThreadStatsTag(int)
+ */
+ public static void clearThreadStatsTag() {
+ sThreadUidTag.get().tag = -1;
+ }
+
+ /**
+ * Set specific UID to use when accounting {@link Socket} traffic
+ * originating from the current thread. Designed for use when performing an
+ * operation on behalf of another application, or when another application
+ * is performing operations on your behalf.
+ * <p>
+ * Any app can <em>accept</em> blame for traffic performed on a socket
+ * originally created by another app by calling this method with the
+ * {@link android.system.Os#getuid()} value. However, only apps holding the
+ * {@code android.Manifest.permission#UPDATE_DEVICE_STATS} permission may
+ * <em>assign</em> blame to another UIDs.
+ * <p>
+ * Changes only take effect during subsequent calls to
+ * {@link #tagSocket(Socket)}.
+ */
+ @SuppressLint("RequiresPermission")
+ public static void setThreadStatsUid(int uid) {
+ sThreadUidTag.get().uid = uid;
+ }
+
+ /**
+ * Get the active UID used when accounting {@link Socket} traffic originating
+ * from the current thread. Only one active tag per thread is supported.
+ * {@link #tagSocket(Socket)}.
+ *
+ * @see #setThreadStatsUid(int)
+ */
+ public static int getThreadStatsUid() {
+ return sThreadUidTag.get().uid;
+ }
+
+ /**
+ * Set specific UID to use when accounting {@link Socket} traffic
+ * originating from the current thread as the calling UID. Designed for use
+ * when another application is performing operations on your behalf.
+ * <p>
+ * Changes only take effect during subsequent calls to
+ * {@link #tagSocket(Socket)}.
+ *
+ * @removed
+ * @deprecated use {@link #setThreadStatsUid(int)} instead.
+ */
+ @Deprecated
+ public static void setThreadStatsUidSelf() {
+ setThreadStatsUid(android.os.Process.myUid());
+ }
+
+ /**
+ * Clear any active UID set to account {@link Socket} traffic originating
+ * from the current thread.
+ *
+ * @see #setThreadStatsUid(int)
+ */
+ @SuppressLint("RequiresPermission")
+ public static void clearThreadStatsUid() {
+ setThreadStatsUid(-1);
+ }
+
+ /**
+ * Tag the given {@link Socket} with any statistics parameters active for
+ * the current thread. Subsequent calls always replace any existing
+ * parameters. When finished, call {@link #untagSocket(Socket)} to remove
+ * statistics parameters.
+ *
+ * @see #setThreadStatsTag(int)
+ */
+ public static void tagSocket(@NonNull Socket socket) throws SocketException {
+ SocketTagger.get().tag(socket);
+ }
+
+ /**
+ * Remove any statistics parameters from the given {@link Socket}.
+ * <p>
+ * In Android 8.1 (API level 27) and lower, a socket is automatically
+ * untagged when it's sent to another process using binder IPC with a
+ * {@code ParcelFileDescriptor} container. In Android 9.0 (API level 28)
+ * and higher, the socket tag is kept when the socket is sent to another
+ * process using binder IPC. You can mimic the previous behavior by
+ * calling {@code untagSocket()} before sending the socket to another
+ * process.
+ */
+ public static void untagSocket(@NonNull Socket socket) throws SocketException {
+ SocketTagger.get().untag(socket);
+ }
+
+ /**
+ * Tag the given {@link DatagramSocket} with any statistics parameters
+ * active for the current thread. Subsequent calls always replace any
+ * existing parameters. When finished, call
+ * {@link #untagDatagramSocket(DatagramSocket)} to remove statistics
+ * parameters.
+ *
+ * @see #setThreadStatsTag(int)
+ */
+ public static void tagDatagramSocket(@NonNull DatagramSocket socket) throws SocketException {
+ SocketTagger.get().tag(socket);
+ }
+
+ /**
+ * Remove any statistics parameters from the given {@link DatagramSocket}.
+ */
+ public static void untagDatagramSocket(@NonNull DatagramSocket socket) throws SocketException {
+ SocketTagger.get().untag(socket);
+ }
+
+ /**
+ * Tag the given {@link FileDescriptor} socket with any statistics
+ * parameters active for the current thread. Subsequent calls always replace
+ * any existing parameters. When finished, call
+ * {@link #untagFileDescriptor(FileDescriptor)} to remove statistics
+ * parameters.
+ *
+ * @see #setThreadStatsTag(int)
+ */
+ public static void tagFileDescriptor(@NonNull FileDescriptor fd) throws IOException {
+ SocketTagger.get().tag(fd);
+ }
+
+ /**
+ * Remove any statistics parameters from the given {@link FileDescriptor}
+ * socket.
+ */
+ public static void untagFileDescriptor(@NonNull FileDescriptor fd) throws IOException {
+ SocketTagger.get().untag(fd);
+ }
+
+ /**
+ * Start profiling data usage for current UID. Only one profiling session
+ * can be active at a time.
+ *
+ * @hide
+ */
+ public static void startDataProfiling(Context context) {
+ synchronized (sProfilingLock) {
+ if (sActiveProfilingStart != null) {
+ throw new IllegalStateException("already profiling data");
+ }
+
+ // take snapshot in time; we calculate delta later
+ sActiveProfilingStart = getDataLayerSnapshotForUid(context);
+ }
+ }
+
+ /**
+ * Stop profiling data usage for current UID.
+ *
+ * @return Detailed {@link NetworkStats} of data that occurred since last
+ * {@link #startDataProfiling(Context)} call.
+ * @hide
+ */
+ public static NetworkStats stopDataProfiling(Context context) {
+ synchronized (sProfilingLock) {
+ if (sActiveProfilingStart == null) {
+ throw new IllegalStateException("not profiling data");
+ }
+
+ // subtract starting values and return delta
+ final NetworkStats profilingStop = getDataLayerSnapshotForUid(context);
+ final NetworkStats profilingDelta = NetworkStats.subtract(
+ profilingStop, sActiveProfilingStart, null, null);
+ sActiveProfilingStart = null;
+ return profilingDelta;
+ }
+ }
+
+ /**
+ * Increment count of network operations performed under the accounting tag
+ * currently active on the calling thread. This can be used to derive
+ * bytes-per-operation.
+ *
+ * @param operationCount Number of operations to increment count by.
+ */
+ public static void incrementOperationCount(int operationCount) {
+ final int tag = getThreadStatsTag();
+ incrementOperationCount(tag, operationCount);
+ }
+
+ /**
+ * Increment count of network operations performed under the given
+ * accounting tag. This can be used to derive bytes-per-operation.
+ *
+ * @param tag Accounting tag used in {@link #setThreadStatsTag(int)}.
+ * @param operationCount Number of operations to increment count by.
+ */
+ public static void incrementOperationCount(int tag, int operationCount) {
+ final int uid = android.os.Process.myUid();
+ try {
+ getStatsService().incrementOperationCount(uid, tag, operationCount);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** {@hide} */
+ public static void closeQuietly(INetworkStatsSession session) {
+ // TODO: move to NetworkStatsService once it exists
+ if (session != null) {
+ try {
+ session.close();
+ } catch (RuntimeException rethrown) {
+ throw rethrown;
+ } catch (Exception ignored) {
+ }
+ }
+ }
+
+ private static long addIfSupported(long stat) {
+ return (stat == UNSUPPORTED) ? 0 : stat;
+ }
+
+ /**
+ * Return number of packets transmitted across mobile networks since device
+ * boot. Counts packets across all mobile network interfaces, and always
+ * increases monotonically since device boot. Statistics are measured at the
+ * network layer, so they include both TCP and UDP usage.
+ * <p>
+ * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
+ * return {@link #UNSUPPORTED} on devices where statistics aren't available.
+ */
+ public static long getMobileTxPackets() {
+ long total = 0;
+ for (String iface : getMobileIfaces()) {
+ total += addIfSupported(getTxPackets(iface));
+ }
+ return total;
+ }
+
+ /**
+ * Return number of packets received across mobile networks since device
+ * boot. Counts packets across all mobile network interfaces, and always
+ * increases monotonically since device boot. Statistics are measured at the
+ * network layer, so they include both TCP and UDP usage.
+ * <p>
+ * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
+ * return {@link #UNSUPPORTED} on devices where statistics aren't available.
+ */
+ public static long getMobileRxPackets() {
+ long total = 0;
+ for (String iface : getMobileIfaces()) {
+ total += addIfSupported(getRxPackets(iface));
+ }
+ return total;
+ }
+
+ /**
+ * Return number of bytes transmitted across mobile networks since device
+ * boot. Counts packets across all mobile network interfaces, and always
+ * increases monotonically since device boot. Statistics are measured at the
+ * network layer, so they include both TCP and UDP usage.
+ * <p>
+ * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
+ * return {@link #UNSUPPORTED} on devices where statistics aren't available.
+ */
+ public static long getMobileTxBytes() {
+ long total = 0;
+ for (String iface : getMobileIfaces()) {
+ total += addIfSupported(getTxBytes(iface));
+ }
+ return total;
+ }
+
+ /**
+ * Return number of bytes received across mobile networks since device boot.
+ * Counts packets across all mobile network interfaces, and always increases
+ * monotonically since device boot. Statistics are measured at the network
+ * layer, so they include both TCP and UDP usage.
+ * <p>
+ * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
+ * return {@link #UNSUPPORTED} on devices where statistics aren't available.
+ */
+ public static long getMobileRxBytes() {
+ long total = 0;
+ for (String iface : getMobileIfaces()) {
+ total += addIfSupported(getRxBytes(iface));
+ }
+ return total;
+ }
+
+ /** {@hide} */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public static long getMobileTcpRxPackets() {
+ long total = 0;
+ for (String iface : getMobileIfaces()) {
+ long stat = UNSUPPORTED;
+ try {
+ stat = getStatsService().getIfaceStats(iface, TYPE_TCP_RX_PACKETS);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ total += addIfSupported(stat);
+ }
+ return total;
+ }
+
+ /** {@hide} */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public static long getMobileTcpTxPackets() {
+ long total = 0;
+ for (String iface : getMobileIfaces()) {
+ long stat = UNSUPPORTED;
+ try {
+ stat = getStatsService().getIfaceStats(iface, TYPE_TCP_TX_PACKETS);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ total += addIfSupported(stat);
+ }
+ return total;
+ }
+
+ /**
+ * Return the number of packets transmitted on the specified interface since the interface
+ * was created. Statistics are measured at the network layer, so both TCP and
+ * UDP usage are included.
+ *
+ * Note that the returned values are partial statistics that do not count data from several
+ * sources and do not apply several adjustments that are necessary for correctness, such
+ * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
+ * determine whether traffic is being transferred on the specific interface but are not a
+ * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
+ * APIs.
+ *
+ * @param iface The name of the interface.
+ * @return The number of transmitted packets.
+ */
+ public static long getTxPackets(@NonNull String iface) {
+ try {
+ return getStatsService().getIfaceStats(iface, TYPE_TX_PACKETS);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return the number of packets received on the specified interface since the interface was
+ * created. Statistics are measured at the network layer, so both TCP
+ * and UDP usage are included.
+ *
+ * Note that the returned values are partial statistics that do not count data from several
+ * sources and do not apply several adjustments that are necessary for correctness, such
+ * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
+ * determine whether traffic is being transferred on the specific interface but are not a
+ * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
+ * APIs.
+ *
+ * @param iface The name of the interface.
+ * @return The number of received packets.
+ */
+ public static long getRxPackets(@NonNull String iface) {
+ try {
+ return getStatsService().getIfaceStats(iface, TYPE_RX_PACKETS);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return the number of bytes transmitted on the specified interface since the interface
+ * was created. Statistics are measured at the network layer, so both TCP and
+ * UDP usage are included.
+ *
+ * Note that the returned values are partial statistics that do not count data from several
+ * sources and do not apply several adjustments that are necessary for correctness, such
+ * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
+ * determine whether traffic is being transferred on the specific interface but are not a
+ * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
+ * APIs.
+ *
+ * @param iface The name of the interface.
+ * @return The number of transmitted bytes.
+ */
+ public static long getTxBytes(@NonNull String iface) {
+ try {
+ return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return the number of bytes received on the specified interface since the interface
+ * was created. Statistics are measured at the network layer, so both TCP
+ * and UDP usage are included.
+ *
+ * Note that the returned values are partial statistics that do not count data from several
+ * sources and do not apply several adjustments that are necessary for correctness, such
+ * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
+ * determine whether traffic is being transferred on the specific interface but are not a
+ * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
+ * APIs.
+ *
+ * @param iface The name of the interface.
+ * @return The number of received bytes.
+ */
+ public static long getRxBytes(@NonNull String iface) {
+ try {
+ return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** {@hide} */
+ @TestApi
+ public static long getLoopbackTxPackets() {
+ try {
+ return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_PACKETS);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** {@hide} */
+ @TestApi
+ public static long getLoopbackRxPackets() {
+ try {
+ return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_PACKETS);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** {@hide} */
+ @TestApi
+ public static long getLoopbackTxBytes() {
+ try {
+ return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_BYTES);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** {@hide} */
+ @TestApi
+ public static long getLoopbackRxBytes() {
+ try {
+ return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_BYTES);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return number of packets transmitted since device boot. Counts packets
+ * across all network interfaces, and always increases monotonically since
+ * device boot. Statistics are measured at the network layer, so they
+ * include both TCP and UDP usage.
+ * <p>
+ * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
+ * return {@link #UNSUPPORTED} on devices where statistics aren't available.
+ */
+ public static long getTotalTxPackets() {
+ try {
+ return getStatsService().getTotalStats(TYPE_TX_PACKETS);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return number of packets received since device boot. Counts packets
+ * across all network interfaces, and always increases monotonically since
+ * device boot. Statistics are measured at the network layer, so they
+ * include both TCP and UDP usage.
+ * <p>
+ * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
+ * return {@link #UNSUPPORTED} on devices where statistics aren't available.
+ */
+ public static long getTotalRxPackets() {
+ try {
+ return getStatsService().getTotalStats(TYPE_RX_PACKETS);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return number of bytes transmitted since device boot. Counts packets
+ * across all network interfaces, and always increases monotonically since
+ * device boot. Statistics are measured at the network layer, so they
+ * include both TCP and UDP usage.
+ * <p>
+ * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
+ * return {@link #UNSUPPORTED} on devices where statistics aren't available.
+ */
+ public static long getTotalTxBytes() {
+ try {
+ return getStatsService().getTotalStats(TYPE_TX_BYTES);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return number of bytes received since device boot. Counts packets across
+ * all network interfaces, and always increases monotonically since device
+ * boot. Statistics are measured at the network layer, so they include both
+ * TCP and UDP usage.
+ * <p>
+ * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
+ * return {@link #UNSUPPORTED} on devices where statistics aren't available.
+ */
+ public static long getTotalRxBytes() {
+ try {
+ return getStatsService().getTotalStats(TYPE_RX_BYTES);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return number of bytes transmitted by the given UID since device boot.
+ * Counts packets across all network interfaces, and always increases
+ * monotonically since device boot. Statistics are measured at the network
+ * layer, so they include both TCP and UDP usage.
+ * <p>
+ * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
+ * return {@link #UNSUPPORTED} on devices where statistics aren't available.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
+ * report traffic statistics for the calling UID. It will return
+ * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
+ * historical network statistics belonging to other UIDs, use
+ * {@link NetworkStatsManager}.
+ *
+ * @see android.os.Process#myUid()
+ * @see android.content.pm.ApplicationInfo#uid
+ */
+ public static long getUidTxBytes(int uid) {
+ try {
+ return getStatsService().getUidStats(uid, TYPE_TX_BYTES);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return number of bytes received by the given UID since device boot.
+ * Counts packets across all network interfaces, and always increases
+ * monotonically since device boot. Statistics are measured at the network
+ * layer, so they include both TCP and UDP usage.
+ * <p>
+ * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
+ * {@link #UNSUPPORTED} on devices where statistics aren't available.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
+ * report traffic statistics for the calling UID. It will return
+ * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
+ * historical network statistics belonging to other UIDs, use
+ * {@link NetworkStatsManager}.
+ *
+ * @see android.os.Process#myUid()
+ * @see android.content.pm.ApplicationInfo#uid
+ */
+ public static long getUidRxBytes(int uid) {
+ try {
+ return getStatsService().getUidStats(uid, TYPE_RX_BYTES);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return number of packets transmitted by the given UID since device boot.
+ * Counts packets across all network interfaces, and always increases
+ * monotonically since device boot. Statistics are measured at the network
+ * layer, so they include both TCP and UDP usage.
+ * <p>
+ * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
+ * {@link #UNSUPPORTED} on devices where statistics aren't available.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
+ * report traffic statistics for the calling UID. It will return
+ * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
+ * historical network statistics belonging to other UIDs, use
+ * {@link NetworkStatsManager}.
+ *
+ * @see android.os.Process#myUid()
+ * @see android.content.pm.ApplicationInfo#uid
+ */
+ public static long getUidTxPackets(int uid) {
+ try {
+ return getStatsService().getUidStats(uid, TYPE_TX_PACKETS);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return number of packets received by the given UID since device boot.
+ * Counts packets across all network interfaces, and always increases
+ * monotonically since device boot. Statistics are measured at the network
+ * layer, so they include both TCP and UDP usage.
+ * <p>
+ * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
+ * {@link #UNSUPPORTED} on devices where statistics aren't available.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
+ * report traffic statistics for the calling UID. It will return
+ * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
+ * historical network statistics belonging to other UIDs, use
+ * {@link NetworkStatsManager}.
+ *
+ * @see android.os.Process#myUid()
+ * @see android.content.pm.ApplicationInfo#uid
+ */
+ public static long getUidRxPackets(int uid) {
+ try {
+ return getStatsService().getUidStats(uid, TYPE_RX_PACKETS);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
+ * transport layer statistics are no longer available, and will
+ * always return {@link #UNSUPPORTED}.
+ * @see #getUidTxBytes(int)
+ */
+ @Deprecated
+ public static long getUidTcpTxBytes(int uid) {
+ return UNSUPPORTED;
+ }
+
+ /**
+ * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
+ * transport layer statistics are no longer available, and will
+ * always return {@link #UNSUPPORTED}.
+ * @see #getUidRxBytes(int)
+ */
+ @Deprecated
+ public static long getUidTcpRxBytes(int uid) {
+ return UNSUPPORTED;
+ }
+
+ /**
+ * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
+ * transport layer statistics are no longer available, and will
+ * always return {@link #UNSUPPORTED}.
+ * @see #getUidTxBytes(int)
+ */
+ @Deprecated
+ public static long getUidUdpTxBytes(int uid) {
+ return UNSUPPORTED;
+ }
+
+ /**
+ * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
+ * transport layer statistics are no longer available, and will
+ * always return {@link #UNSUPPORTED}.
+ * @see #getUidRxBytes(int)
+ */
+ @Deprecated
+ public static long getUidUdpRxBytes(int uid) {
+ return UNSUPPORTED;
+ }
+
+ /**
+ * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
+ * transport layer statistics are no longer available, and will
+ * always return {@link #UNSUPPORTED}.
+ * @see #getUidTxPackets(int)
+ */
+ @Deprecated
+ public static long getUidTcpTxSegments(int uid) {
+ return UNSUPPORTED;
+ }
+
+ /**
+ * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
+ * transport layer statistics are no longer available, and will
+ * always return {@link #UNSUPPORTED}.
+ * @see #getUidRxPackets(int)
+ */
+ @Deprecated
+ public static long getUidTcpRxSegments(int uid) {
+ return UNSUPPORTED;
+ }
+
+ /**
+ * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
+ * transport layer statistics are no longer available, and will
+ * always return {@link #UNSUPPORTED}.
+ * @see #getUidTxPackets(int)
+ */
+ @Deprecated
+ public static long getUidUdpTxPackets(int uid) {
+ return UNSUPPORTED;
+ }
+
+ /**
+ * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
+ * transport layer statistics are no longer available, and will
+ * always return {@link #UNSUPPORTED}.
+ * @see #getUidRxPackets(int)
+ */
+ @Deprecated
+ public static long getUidUdpRxPackets(int uid) {
+ return UNSUPPORTED;
+ }
+
+ /**
+ * Return detailed {@link NetworkStats} for the current UID. Requires no
+ * special permission.
+ */
+ private static NetworkStats getDataLayerSnapshotForUid(Context context) {
+ // TODO: take snapshot locally, since proc file is now visible
+ final int uid = android.os.Process.myUid();
+ try {
+ return getStatsService().getDataLayerSnapshotForUid(uid);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return set of any ifaces associated with mobile networks since boot.
+ * Interfaces are never removed from this list, so counters should always be
+ * monotonic.
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
+ private static String[] getMobileIfaces() {
+ try {
+ return getStatsService().getMobileIfaces();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ // NOTE: keep these in sync with {@code com_android_server_net_NetworkStatsService.cpp}.
+ /** {@hide} */
+ public static final int TYPE_RX_BYTES = 0;
+ /** {@hide} */
+ public static final int TYPE_RX_PACKETS = 1;
+ /** {@hide} */
+ public static final int TYPE_TX_BYTES = 2;
+ /** {@hide} */
+ public static final int TYPE_TX_PACKETS = 3;
+ /** {@hide} */
+ public static final int TYPE_TCP_RX_PACKETS = 4;
+ /** {@hide} */
+ public static final int TYPE_TCP_TX_PACKETS = 5;
+}