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
17package android.net;
18
19import android.app.DownloadManager;
20import android.app.backup.BackupManager;
21import android.content.Context;
22import android.media.MediaPlayer;
23import android.os.RemoteException;
24import android.os.ServiceManager;
25
26import com.android.server.NetworkManagementSocketTagger;
27
28import dalvik.system.SocketTagger;
29
30import java.net.Socket;
31import 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 */
41public 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