content: /*
   * 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 android.annotation.SuppressLint;
  import android.annotation.SystemApi;
  import android.annotation.TestApi;
  import android.annotation.UnsupportedAppUsage;
  import android.app.DownloadManager;
  import android.app.backup.BackupManager;
  import android.app.usage.NetworkStatsManager;
  import android.content.Context;
  import android.media.MediaPlayer;
  import android.os.Build;
  import android.os.RemoteException;
  import android.os.ServiceManager;
  import android.util.DataUnit;
  
  import com.android.server.NetworkManagementSocketTagger;
  
  import dalvik.system.SocketTagger;
  
  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 {
      /**
       * The return value to indicate that the device does not support the statistic.
       */
      public final static int UNSUPPORTED = -1;
  
      /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
      @Deprecated
      public static final long KB_IN_BYTES = 1024;
      /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
      @Deprecated
      public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
      /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
      @Deprecated
      public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
      /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
      @Deprecated
      public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
      /** @hide @deprecated use {@link 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 = -5;
  
      /**
       * 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) {
              sStatsService = INetworkStatsService.Stub.asInterface(
                      ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
          }
          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";
  
      /**
       * 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) {
          NetworkManagementSocketTagger.setThreadSocketStatsTag(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) {
          return NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
      }
  
      /**
       * 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);
      }
  
      /**
       * 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 NetworkManagementSocketTagger.getThreadSocketStatsTag();
      }
  
      /**
       * Clear any active tag set to account {@link Socket} traffic originating
       * from the current thread.
       *
       * @see #setThreadStatsTag(int)
       */
      public static void clearThreadStatsTag() {
          NetworkManagementSocketTagger.setThreadSocketStatsTag(-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("Doclava125")
      public static void setThreadStatsUid(int uid) {
          NetworkManagementSocketTagger.setThreadSocketStatsUid(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 NetworkManagementSocketTagger.getThreadSocketStatsUid();
      }
  
      /**
       * 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("Doclava125")
      public static void clearThreadStatsUid() {
          NetworkManagementSocketTagger.setThreadSocketStatsUid(-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(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(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(DatagramSocket socket) throws SocketException {
          SocketTagger.get().tag(socket);
      }
  
      /**
       * Remove any statistics parameters from the given {@link DatagramSocket}.
       */
      public static void untagDatagramSocket(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(FileDescriptor fd) throws IOException {
          SocketTagger.get().tag(fd);
      }
  
      /**
       * Remove any statistics parameters from the given {@link FileDescriptor}
       * socket.
       */
      public static void untagFileDescriptor(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
      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
      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;
      }
  
      /** {@hide} */
      public static long getTxPackets(String iface) {
          try {
              return getStatsService().getIfaceStats(iface, TYPE_TX_PACKETS);
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  
      /** {@hide} */
      public static long getRxPackets(String iface) {
          try {
              return getStatsService().getIfaceStats(iface, TYPE_RX_PACKETS);
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  
      /** {@hide} */
      @UnsupportedAppUsage
      public static long getTxBytes(String iface) {
          try {
              return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES);
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  
      /** {@hide} */
      @UnsupportedAppUsage
      public static long getRxBytes(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) {
          // This isn't actually enforcing any security; it just returns the
          // 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) {
              try {
                  return getStatsService().getUidStats(uid, TYPE_TX_BYTES);
              } catch (RemoteException e) {
                  throw e.rethrowFromSystemServer();
              }
          } else {
              return UNSUPPORTED;
          }
      }
  
      /**
       * 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) {
          // This isn't actually enforcing any security; it just returns the
          // 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) {
              try {
                  return getStatsService().getUidStats(uid, TYPE_RX_BYTES);
              } catch (RemoteException e) {
                  throw e.rethrowFromSystemServer();
              }
          } else {
              return UNSUPPORTED;
          }
      }
  
      /**
       * 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) {
          // This isn't actually enforcing any security; it just returns the
          // 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) {
              try {
                  return getStatsService().getUidStats(uid, TYPE_TX_PACKETS);
              } catch (RemoteException e) {
                  throw e.rethrowFromSystemServer();
              }
          } else {
              return UNSUPPORTED;
          }
      }
  
      /**
       * 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) {
          // This isn't actually enforcing any security; it just returns the
          // 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) {
              try {
                  return getStatsService().getUidStats(uid, TYPE_RX_PACKETS);
              } catch (RemoteException e) {
                  throw e.rethrowFromSystemServer();
              }
          } else {
              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 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 android_net_TrafficStats.cpp
      private static final int TYPE_RX_BYTES = 0;
      private static final int TYPE_RX_PACKETS = 1;
      private static final int TYPE_TX_BYTES = 2;
      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;
  }
  