Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.net;
     18 
     19 import android.app.DownloadManager;
     20 import android.app.backup.BackupManager;
     21 import android.content.Context;
     22 import android.media.MediaPlayer;
     23 import android.os.RemoteException;
     24 import android.os.ServiceManager;
     25 
     26 import com.android.server.NetworkManagementSocketTagger;
     27 
     28 import dalvik.system.SocketTagger;
     29 
     30 import java.net.Socket;
     31 import java.net.SocketException;
     32 
     33 /**
     34  * Class that provides network traffic statistics.  These statistics include
     35  * bytes transmitted and received and network packets transmitted and received,
     36  * over all interfaces, over the mobile interface, and on a per-UID basis.
     37  * <p>
     38  * These statistics may not be available on all platforms.  If the statistics
     39  * are not supported by this device, {@link #UNSUPPORTED} will be returned.
     40  */
     41 public class TrafficStats {
     42     /**
     43      * The return value to indicate that the device does not support the statistic.
     44      */
     45     public final static int UNSUPPORTED = -1;
     46 
     47     /** @hide */
     48     public static final long KB_IN_BYTES = 1024;
     49     /** @hide */
     50     public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
     51     /** @hide */
     52     public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
     53 
     54     /**
     55      * Special UID value used when collecting {@link NetworkStatsHistory} for
     56      * removed applications.
     57      *
     58      * @hide
     59      */
     60     public static final int UID_REMOVED = -4;
     61 
     62     /**
     63      * Special UID value used when collecting {@link NetworkStatsHistory} for
     64      * tethering traffic.
     65      *
     66      * @hide
     67      */
     68     public static final int UID_TETHERING = -5;
     69 
     70     /**
     71      * Default tag value for {@link DownloadManager} traffic.
     72      *
     73      * @hide
     74      */
     75     public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFFFF01;
     76 
     77     /**
     78      * Default tag value for {@link MediaPlayer} traffic.
     79      *
     80      * @hide
     81      */
     82     public static final int TAG_SYSTEM_MEDIA = 0xFFFFFF02;
     83 
     84     /**
     85      * Default tag value for {@link BackupManager} traffic.
     86      *
     87      * @hide
     88      */
     89     public static final int TAG_SYSTEM_BACKUP = 0xFFFFFF03;
     90 
     91     private static INetworkStatsService sStatsService;
     92 
     93     private synchronized static INetworkStatsService getStatsService() {
     94         if (sStatsService == null) {
     95             sStatsService = INetworkStatsService.Stub.asInterface(
     96                     ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
     97         }
     98         return sStatsService;
     99     }
    100 
    101     /**
    102      * Snapshot of {@link NetworkStats} when the currently active profiling
    103      * session started, or {@code null} if no session active.
    104      *
    105      * @see #startDataProfiling(Context)
    106      * @see #stopDataProfiling(Context)
    107      */
    108     private static NetworkStats sActiveProfilingStart;
    109 
    110     private static Object sProfilingLock = new Object();
    111 
    112     /**
    113      * Set active tag to use when accounting {@link Socket} traffic originating
    114      * from the current thread. Only one active tag per thread is supported.
    115      * <p>
    116      * Changes only take effect during subsequent calls to
    117      * {@link #tagSocket(Socket)}.
    118      * <p>
    119      * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
    120      * used internally by system services like {@link DownloadManager} when
    121      * performing traffic on behalf of an application.
    122      */
    123     public static void setThreadStatsTag(int tag) {
    124         NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
    125     }
    126 
    127     /**
    128      * Get the active tag used when accounting {@link Socket} traffic originating
    129      * from the current thread. Only one active tag per thread is supported.
    130      * {@link #tagSocket(Socket)}.
    131      */
    132     public static int getThreadStatsTag() {
    133         return NetworkManagementSocketTagger.getThreadSocketStatsTag();
    134     }
    135 
    136     public static void clearThreadStatsTag() {
    137         NetworkManagementSocketTagger.setThreadSocketStatsTag(-1);
    138     }
    139 
    140     /**
    141      * Set specific UID to use when accounting {@link Socket} traffic
    142      * originating from the current thread. Designed for use when performing an
    143      * operation on behalf of another application.
    144      * <p>
    145      * Changes only take effect during subsequent calls to
    146      * {@link #tagSocket(Socket)}.
    147      * <p>
    148      * To take effect, caller must hold
    149      * {@link android.Manifest.permission#UPDATE_DEVICE_STATS} permission.
    150      *
    151      * {@hide}
    152      */
    153     public static void setThreadStatsUid(int uid) {
    154         NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
    155     }
    156 
    157     /** {@hide} */
    158     public static void clearThreadStatsUid() {
    159         NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
    160     }
    161 
    162     /**
    163      * Tag the given {@link Socket} with any statistics parameters active for
    164      * the current thread. Subsequent calls always replace any existing
    165      * parameters. When finished, call {@link #untagSocket(Socket)} to remove
    166      * statistics parameters.
    167      *
    168      * @see #setThreadStatsTag(int)
    169      * @see #setThreadStatsUid(int)
    170      */
    171     public static void tagSocket(Socket socket) throws SocketException {
    172         SocketTagger.get().tag(socket);
    173     }
    174 
    175     /**
    176      * Remove any statistics parameters from the given {@link Socket}.
    177      */
    178     public static void untagSocket(Socket socket) throws SocketException {
    179         SocketTagger.get().untag(socket);
    180     }
    181 
    182     /**
    183      * Start profiling data usage for current UID. Only one profiling session
    184      * can be active at a time.
    185      *
    186      * @hide
    187      */
    188     public static void startDataProfiling(Context context) {
    189         synchronized (sProfilingLock) {
    190             if (sActiveProfilingStart != null) {
    191                 throw new IllegalStateException("already profiling data");
    192             }
    193 
    194             // take snapshot in time; we calculate delta later
    195             sActiveProfilingStart = getDataLayerSnapshotForUid(context);
    196         }
    197     }
    198 
    199     /**
    200      * Stop profiling data usage for current UID.
    201      *
    202      * @return Detailed {@link NetworkStats} of data that occurred since last
    203      *         {@link #startDataProfiling(Context)} call.
    204      * @hide
    205      */
    206     public static NetworkStats stopDataProfiling(Context context) {
    207         synchronized (sProfilingLock) {
    208             if (sActiveProfilingStart == null) {
    209                 throw new IllegalStateException("not profiling data");
    210             }
    211 
    212             // subtract starting values and return delta
    213             final NetworkStats profilingStop = getDataLayerSnapshotForUid(context);
    214             final NetworkStats profilingDelta = NetworkStats.subtract(
    215                     profilingStop, sActiveProfilingStart, null, null);
    216             sActiveProfilingStart = null;
    217             return profilingDelta;
    218         }
    219     }
    220 
    221     /**
    222      * Increment count of network operations performed under the accounting tag
    223      * currently active on the calling thread. This can be used to derive
    224      * bytes-per-operation.
    225      *
    226      * @param operationCount Number of operations to increment count by.
    227      */
    228     public static void incrementOperationCount(int operationCount) {
    229         final int tag = getThreadStatsTag();
    230         incrementOperationCount(tag, operationCount);
    231     }
    232 
    233     /**
    234      * Increment count of network operations performed under the given
    235      * accounting tag. This can be used to derive bytes-per-operation.
    236      *
    237      * @param tag Accounting tag used in {@link #setThreadStatsTag(int)}.
    238      * @param operationCount Number of operations to increment count by.
    239      */
    240     public static void incrementOperationCount(int tag, int operationCount) {
    241         final int uid = android.os.Process.myUid();
    242         try {
    243             getStatsService().incrementOperationCount(uid, tag, operationCount);
    244         } catch (RemoteException e) {
    245             throw new RuntimeException(e);
    246         }
    247     }
    248 
    249     /** {@hide} */
    250     public static void closeQuietly(INetworkStatsSession session) {
    251         // TODO: move to NetworkStatsService once it exists
    252         if (session != null) {
    253             try {
    254                 session.close();
    255             } catch (RuntimeException rethrown) {
    256                 throw rethrown;
    257             } catch (Exception ignored) {
    258             }
    259         }
    260     }
    261 
    262     /**
    263      * Get the total number of packets transmitted through the mobile interface.
    264      *
    265      * @return number of packets.  If the statistics are not supported by this device,
    266      * {@link #UNSUPPORTED} will be returned.
    267      */
    268     public static long getMobileTxPackets() {
    269         long total = 0;
    270         for (String iface : getMobileIfaces()) {
    271             total += getTxPackets(iface);
    272         }
    273         return total;
    274     }
    275 
    276     /**
    277      * Get the total number of packets received through the mobile interface.
    278      *
    279      * @return number of packets.  If the statistics are not supported by this device,
    280      * {@link #UNSUPPORTED} will be returned.
    281      */
    282     public static long getMobileRxPackets() {
    283         long total = 0;
    284         for (String iface : getMobileIfaces()) {
    285             total += getRxPackets(iface);
    286         }
    287         return total;
    288     }
    289 
    290     /**
    291      * Get the total number of bytes transmitted through the mobile interface.
    292      *
    293      * @return number of bytes.  If the statistics are not supported by this device,
    294      * {@link #UNSUPPORTED} will be returned.
    295      */
    296     public static long getMobileTxBytes() {
    297         long total = 0;
    298         for (String iface : getMobileIfaces()) {
    299             total += getTxBytes(iface);
    300         }
    301         return total;
    302     }
    303 
    304     /**
    305      * Get the total number of bytes received through the mobile interface.
    306      *
    307      * @return number of bytes.  If the statistics are not supported by this device,
    308      * {@link #UNSUPPORTED} will be returned.
    309      */
    310     public static long getMobileRxBytes() {
    311         long total = 0;
    312         for (String iface : getMobileIfaces()) {
    313             total += getRxBytes(iface);
    314         }
    315         return total;
    316     }
    317 
    318     /**
    319      * Get the total number of packets transmitted through the specified interface.
    320      *
    321      * @return number of packets.  If the statistics are not supported by this interface,
    322      * {@link #UNSUPPORTED} will be returned.
    323      * @hide
    324      */
    325     public static long getTxPackets(String iface) {
    326         return nativeGetIfaceStat(iface, TYPE_TX_PACKETS);
    327     }
    328 
    329     /**
    330      * Get the total number of packets received through the specified interface.
    331      *
    332      * @return number of packets.  If the statistics are not supported by this interface,
    333      * {@link #UNSUPPORTED} will be returned.
    334      * @hide
    335      */
    336     public static long getRxPackets(String iface) {
    337         return nativeGetIfaceStat(iface, TYPE_RX_PACKETS);
    338     }
    339 
    340     /**
    341      * Get the total number of bytes transmitted through the specified interface.
    342      *
    343      * @return number of bytes.  If the statistics are not supported by this interface,
    344      * {@link #UNSUPPORTED} will be returned.
    345      * @hide
    346      */
    347     public static long getTxBytes(String iface) {
    348         return nativeGetIfaceStat(iface, TYPE_TX_BYTES);
    349     }
    350 
    351     /**
    352      * Get the total number of bytes received through the specified interface.
    353      *
    354      * @return number of bytes.  If the statistics are not supported by this interface,
    355      * {@link #UNSUPPORTED} will be returned.
    356      * @hide
    357      */
    358     public static long getRxBytes(String iface) {
    359         return nativeGetIfaceStat(iface, TYPE_RX_BYTES);
    360     }
    361 
    362     /**
    363      * Get the total number of packets sent through all network interfaces.
    364      *
    365      * @return the number of packets.  If the statistics are not supported by this device,
    366      * {@link #UNSUPPORTED} will be returned.
    367      */
    368     public static long getTotalTxPackets() {
    369         return nativeGetTotalStat(TYPE_TX_PACKETS);
    370     }
    371 
    372     /**
    373      * Get the total number of packets received through all network interfaces.
    374      *
    375      * @return number of packets.  If the statistics are not supported by this device,
    376      * {@link #UNSUPPORTED} will be returned.
    377      */
    378     public static long getTotalRxPackets() {
    379         return nativeGetTotalStat(TYPE_RX_PACKETS);
    380     }
    381 
    382     /**
    383      * Get the total number of bytes sent through all network interfaces.
    384      *
    385      * @return number of bytes.  If the statistics are not supported by this device,
    386      * {@link #UNSUPPORTED} will be returned.
    387      */
    388     public static long getTotalTxBytes() {
    389         return nativeGetTotalStat(TYPE_TX_BYTES);
    390     }
    391 
    392     /**
    393      * Get the total number of bytes received through all network interfaces.
    394      *
    395      * @return number of bytes.  If the statistics are not supported by this device,
    396      * {@link #UNSUPPORTED} will be returned.
    397      */
    398     public static long getTotalRxBytes() {
    399         return nativeGetTotalStat(TYPE_RX_BYTES);
    400     }
    401 
    402     /**
    403      * Get the number of bytes sent through the network for this UID.
    404      * The statistics are across all interfaces.
    405      *
    406      * {@see android.os.Process#myUid()}.
    407      *
    408      * @param uid The UID of the process to examine.
    409      * @return number of bytes.  If the statistics are not supported by this device,
    410      * {@link #UNSUPPORTED} will be returned.
    411      */
    412     public static native long getUidTxBytes(int uid);
    413 
    414     /**
    415      * Get the number of bytes received through the network for this UID.
    416      * The statistics are across all interfaces.
    417      *
    418      * {@see android.os.Process#myUid()}.
    419      *
    420      * @param uid The UID of the process to examine.
    421      * @return number of bytes
    422      */
    423     public static native long getUidRxBytes(int uid);
    424 
    425     /**
    426      * Get the number of packets (TCP segments + UDP) sent through
    427      * the network for this UID.
    428      * The statistics are across all interfaces.
    429      *
    430      * {@see android.os.Process#myUid()}.
    431      *
    432      * @param uid The UID of the process to examine.
    433      * @return number of packets.
    434      * If the statistics are not supported by this device,
    435      * {@link #UNSUPPORTED} will be returned.
    436      */
    437     public static native long getUidTxPackets(int uid);
    438 
    439     /**
    440      * Get the number of packets (TCP segments + UDP) received through
    441      * the network for this UID.
    442      * The statistics are across all interfaces.
    443      *
    444      * {@see android.os.Process#myUid()}.
    445      *
    446      * @param uid The UID of the process to examine.
    447      * @return number of packets
    448      */
    449     public static native long getUidRxPackets(int uid);
    450 
    451     /**
    452      * Get the number of TCP payload bytes sent for this UID.
    453      * This total does not include protocol and control overheads at
    454      * the transport and the lower layers of the networking stack.
    455      * The statistics are across all interfaces.
    456      *
    457      * {@see android.os.Process#myUid()}.
    458      *
    459      * @param uid The UID of the process to examine.
    460      * @return number of bytes.  If the statistics are not supported by this device,
    461      * {@link #UNSUPPORTED} will be returned.
    462      */
    463     public static native long getUidTcpTxBytes(int uid);
    464 
    465     /**
    466      * Get the number of TCP payload bytes received for this UID.
    467      * This total does not include protocol and control overheads at
    468      * the transport and the lower layers of the networking stack.
    469      * The statistics are across all interfaces.
    470      *
    471      * {@see android.os.Process#myUid()}.
    472      *
    473      * @param uid The UID of the process to examine.
    474      * @return number of bytes.  If the statistics are not supported by this device,
    475      * {@link #UNSUPPORTED} will be returned.
    476      */
    477     public static native long getUidTcpRxBytes(int uid);
    478 
    479     /**
    480      * Get the number of UDP payload bytes sent for this UID.
    481      * This total does not include protocol and control overheads at
    482      * the transport and the lower layers of the networking stack.
    483      * The statistics are across all interfaces.
    484      *
    485      * {@see android.os.Process#myUid()}.
    486      *
    487      * @param uid The UID of the process to examine.
    488      * @return number of bytes.  If the statistics are not supported by this device,
    489      * {@link #UNSUPPORTED} will be returned.
    490      */
    491     public static native long getUidUdpTxBytes(int uid);
    492 
    493     /**
    494      * Get the number of UDP payload bytes received for this UID.
    495      * This total does not include protocol and control overheads at
    496      * the transport and the lower layers of the networking stack.
    497      * The statistics are across all interfaces.
    498      *
    499      * {@see android.os.Process#myUid()}.
    500      *
    501      * @param uid The UID of the process to examine.
    502      * @return number of bytes.  If the statistics are not supported by this device,
    503      * {@link #UNSUPPORTED} will be returned.
    504      */
    505     public static native long getUidUdpRxBytes(int uid);
    506 
    507     /**
    508      * Get the number of TCP segments sent for this UID.
    509      * Does not include TCP control packets (SYN/ACKs/FIN/..).
    510      * The statistics are across all interfaces.
    511      *
    512      * {@see android.os.Process#myUid()}.
    513      *
    514      * @param uid The UID of the process to examine.
    515      * @return number of TCP segments.  If the statistics are not supported by this device,
    516      * {@link #UNSUPPORTED} will be returned.
    517      */
    518     public static native long getUidTcpTxSegments(int uid);
    519 
    520     /**
    521      * Get the number of TCP segments received for this UID.
    522      * Does not include TCP control packets (SYN/ACKs/FIN/..).
    523      * The statistics are across all interfaces.
    524      *
    525      * {@see android.os.Process#myUid()}.
    526      *
    527      * @param uid The UID of the process to examine.
    528      * @return number of TCP segments.  If the statistics are not supported by this device,
    529      * {@link #UNSUPPORTED} will be returned.
    530      */
    531     public static native long getUidTcpRxSegments(int uid);
    532 
    533     /**
    534      * Get the number of UDP packets sent for this UID.
    535      * Includes DNS requests.
    536      * The statistics are across all interfaces.
    537      *
    538      * {@see android.os.Process#myUid()}.
    539      *
    540      * @param uid The UID of the process to examine.
    541      * @return number of packets.  If the statistics are not supported by this device,
    542      * {@link #UNSUPPORTED} will be returned.
    543      */
    544     public static native long getUidUdpTxPackets(int uid);
    545 
    546     /**
    547      * Get the number of UDP packets received for this UID.
    548      * Includes DNS responses.
    549      * The statistics are across all interfaces.
    550      *
    551      * {@see android.os.Process#myUid()}.
    552      *
    553      * @param uid The UID of the process to examine.
    554      * @return number of packets.  If the statistics are not supported by this device,
    555      * {@link #UNSUPPORTED} will be returned.
    556      */
    557     public static native long getUidUdpRxPackets(int uid);
    558 
    559     /**
    560      * Return detailed {@link NetworkStats} for the current UID. Requires no
    561      * special permission.
    562      */
    563     private static NetworkStats getDataLayerSnapshotForUid(Context context) {
    564         final int uid = android.os.Process.myUid();
    565         try {
    566             return getStatsService().getDataLayerSnapshotForUid(uid);
    567         } catch (RemoteException e) {
    568             throw new RuntimeException(e);
    569         }
    570     }
    571 
    572     /**
    573      * Return set of any ifaces associated with mobile networks since boot.
    574      * Interfaces are never removed from this list, so counters should always be
    575      * monotonic.
    576      */
    577     private static String[] getMobileIfaces() {
    578         try {
    579             return getStatsService().getMobileIfaces();
    580         } catch (RemoteException e) {
    581             throw new RuntimeException(e);
    582         }
    583     }
    584 
    585     // NOTE: keep these in sync with android_net_TrafficStats.cpp
    586     private static final int TYPE_RX_BYTES = 0;
    587     private static final int TYPE_RX_PACKETS = 1;
    588     private static final int TYPE_TX_BYTES = 2;
    589     private static final int TYPE_TX_PACKETS = 3;
    590 
    591     private static native long nativeGetTotalStat(int type);
    592     private static native long nativeGetIfaceStat(String iface, int type);
    593 }
    594