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.net.NetworkStats.NonMonotonicException;
24import android.os.RemoteException;
25import android.os.ServiceManager;
26
27import com.android.server.NetworkManagementSocketTagger;
28
29import dalvik.system.SocketTagger;
30
31import java.net.Socket;
32import java.net.SocketException;
33
34/**
35 * Class that provides network traffic statistics.  These statistics include
36 * bytes transmitted and received and network packets transmitted and received,
37 * over all interfaces, over the mobile interface, and on a per-UID basis.
38 * <p>
39 * These statistics may not be available on all platforms.  If the statistics
40 * are not supported by this device, {@link #UNSUPPORTED} will be returned.
41 */
42public class TrafficStats {
43    /**
44     * The return value to indicate that the device does not support the statistic.
45     */
46    public final static int UNSUPPORTED = -1;
47
48    /**
49     * Special UID value used when collecting {@link NetworkStatsHistory} for
50     * removed applications.
51     *
52     * @hide
53     */
54    public static final int UID_REMOVED = -4;
55
56    /**
57     * Special UID value used when collecting {@link NetworkStatsHistory} for
58     * tethering traffic.
59     *
60     * @hide
61     */
62    public static final int UID_TETHERING = -5;
63
64    /**
65     * Default tag value for {@link DownloadManager} traffic.
66     *
67     * @hide
68     */
69    public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFFFF01;
70
71    /**
72     * Default tag value for {@link MediaPlayer} traffic.
73     *
74     * @hide
75     */
76    public static final int TAG_SYSTEM_MEDIA = 0xFFFFFF02;
77
78    /**
79     * Default tag value for {@link BackupManager} traffic.
80     *
81     * @hide
82     */
83    public static final int TAG_SYSTEM_BACKUP = 0xFFFFFF03;
84
85    /**
86     * Snapshot of {@link NetworkStats} when the currently active profiling
87     * session started, or {@code null} if no session active.
88     *
89     * @see #startDataProfiling(Context)
90     * @see #stopDataProfiling(Context)
91     */
92    private static NetworkStats sActiveProfilingStart;
93
94    private static Object sProfilingLock = new Object();
95
96    /**
97     * Set active tag to use when accounting {@link Socket} traffic originating
98     * from the current thread. Only one active tag per thread is supported.
99     * <p>
100     * Changes only take effect during subsequent calls to
101     * {@link #tagSocket(Socket)}.
102     * <p>
103     * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
104     * used internally by system services like {@link DownloadManager} when
105     * performing traffic on behalf of an application.
106     */
107    public static void setThreadStatsTag(int tag) {
108        NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
109    }
110
111    /**
112     * Get the active tag used when accounting {@link Socket} traffic originating
113     * from the current thread. Only one active tag per thread is supported.
114     * {@link #tagSocket(Socket)}.
115     */
116    public static int getThreadStatsTag() {
117        return NetworkManagementSocketTagger.getThreadSocketStatsTag();
118    }
119
120    public static void clearThreadStatsTag() {
121        NetworkManagementSocketTagger.setThreadSocketStatsTag(-1);
122    }
123
124    /**
125     * Set specific UID to use when accounting {@link Socket} traffic
126     * originating from the current thread. Designed for use when performing an
127     * operation on behalf of another application.
128     * <p>
129     * Changes only take effect during subsequent calls to
130     * {@link #tagSocket(Socket)}.
131     * <p>
132     * To take effect, caller must hold
133     * {@link android.Manifest.permission#UPDATE_DEVICE_STATS} permission.
134     *
135     * {@hide}
136     */
137    public static void setThreadStatsUid(int uid) {
138        NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
139    }
140
141    /** {@hide} */
142    public static void clearThreadStatsUid() {
143        NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
144    }
145
146    /**
147     * Tag the given {@link Socket} with any statistics parameters active for
148     * the current thread. Subsequent calls always replace any existing
149     * parameters. When finished, call {@link #untagSocket(Socket)} to remove
150     * statistics parameters.
151     *
152     * @see #setThreadStatsTag(int)
153     * @see #setThreadStatsUid(int)
154     */
155    public static void tagSocket(Socket socket) throws SocketException {
156        SocketTagger.get().tag(socket);
157    }
158
159    /**
160     * Remove any statistics parameters from the given {@link Socket}.
161     */
162    public static void untagSocket(Socket socket) throws SocketException {
163        SocketTagger.get().untag(socket);
164    }
165
166    /**
167     * Start profiling data usage for current UID. Only one profiling session
168     * can be active at a time.
169     *
170     * @hide
171     */
172    public static void startDataProfiling(Context context) {
173        synchronized (sProfilingLock) {
174            if (sActiveProfilingStart != null) {
175                throw new IllegalStateException("already profiling data");
176            }
177
178            // take snapshot in time; we calculate delta later
179            sActiveProfilingStart = getDataLayerSnapshotForUid(context);
180        }
181    }
182
183    /**
184     * Stop profiling data usage for current UID.
185     *
186     * @return Detailed {@link NetworkStats} of data that occurred since last
187     *         {@link #startDataProfiling(Context)} call.
188     * @hide
189     */
190    public static NetworkStats stopDataProfiling(Context context) {
191        synchronized (sProfilingLock) {
192            if (sActiveProfilingStart == null) {
193                throw new IllegalStateException("not profiling data");
194            }
195
196            try {
197                // subtract starting values and return delta
198                final NetworkStats profilingStop = getDataLayerSnapshotForUid(context);
199                final NetworkStats profilingDelta = profilingStop.subtract(sActiveProfilingStart);
200                sActiveProfilingStart = null;
201                return profilingDelta;
202            } catch (NonMonotonicException e) {
203                throw new RuntimeException(e);
204            }
205        }
206    }
207
208    /**
209     * Increment count of network operations performed under the accounting tag
210     * currently active on the calling thread. This can be used to derive
211     * bytes-per-operation.
212     *
213     * @param operationCount Number of operations to increment count by.
214     */
215    public static void incrementOperationCount(int operationCount) {
216        final int tag = getThreadStatsTag();
217        incrementOperationCount(tag, operationCount);
218    }
219
220    /**
221     * Increment count of network operations performed under the given
222     * accounting tag. This can be used to derive bytes-per-operation.
223     *
224     * @param tag Accounting tag used in {@link #setThreadStatsTag(int)}.
225     * @param operationCount Number of operations to increment count by.
226     */
227    public static void incrementOperationCount(int tag, int operationCount) {
228        final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
229                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
230        final int uid = android.os.Process.myUid();
231        try {
232            statsService.incrementOperationCount(uid, tag, operationCount);
233        } catch (RemoteException e) {
234            throw new RuntimeException(e);
235        }
236    }
237
238    /**
239     * Get the total number of packets transmitted through the mobile interface.
240     *
241     * @return number of packets.  If the statistics are not supported by this device,
242     * {@link #UNSUPPORTED} will be returned.
243     */
244    public static native long getMobileTxPackets();
245
246    /**
247     * Get the total number of packets received through the mobile interface.
248     *
249     * @return number of packets.  If the statistics are not supported by this device,
250     * {@link #UNSUPPORTED} will be returned.
251     */
252    public static native long getMobileRxPackets();
253
254    /**
255     * Get the total number of bytes transmitted through the mobile interface.
256     *
257     * @return number of bytes.  If the statistics are not supported by this device,
258     * {@link #UNSUPPORTED} will be returned.
259     */
260      public static native long getMobileTxBytes();
261
262    /**
263     * Get the total number of bytes received through the mobile interface.
264     *
265     * @return number of bytes.  If the statistics are not supported by this device,
266     * {@link #UNSUPPORTED} will be returned.
267     */
268    public static native long getMobileRxBytes();
269
270    /**
271     * Get the total number of packets transmitted through the specified interface.
272     *
273     * @return number of packets.  If the statistics are not supported by this interface,
274     * {@link #UNSUPPORTED} will be returned.
275     * @hide
276     */
277    public static native long getTxPackets(String iface);
278
279    /**
280     * Get the total number of packets received through the specified interface.
281     *
282     * @return number of packets.  If the statistics are not supported by this interface,
283     * {@link #UNSUPPORTED} will be returned.
284     * @hide
285     */
286    public static native long getRxPackets(String iface);
287
288    /**
289     * Get the total number of bytes transmitted through the specified interface.
290     *
291     * @return number of bytes.  If the statistics are not supported by this interface,
292     * {@link #UNSUPPORTED} will be returned.
293     * @hide
294     */
295    public static native long getTxBytes(String iface);
296
297    /**
298     * Get the total number of bytes received through the specified interface.
299     *
300     * @return number of bytes.  If the statistics are not supported by this interface,
301     * {@link #UNSUPPORTED} will be returned.
302     * @hide
303     */
304    public static native long getRxBytes(String iface);
305
306
307    /**
308     * Get the total number of packets sent through all network interfaces.
309     *
310     * @return the number of packets.  If the statistics are not supported by this device,
311     * {@link #UNSUPPORTED} will be returned.
312     */
313    public static native long getTotalTxPackets();
314
315    /**
316     * Get the total number of packets received through all network interfaces.
317     *
318     * @return number of packets.  If the statistics are not supported by this device,
319     * {@link #UNSUPPORTED} will be returned.
320     */
321    public static native long getTotalRxPackets();
322
323    /**
324     * Get the total number of bytes sent through all network interfaces.
325     *
326     * @return number of bytes.  If the statistics are not supported by this device,
327     * {@link #UNSUPPORTED} will be returned.
328     */
329    public static native long getTotalTxBytes();
330
331    /**
332     * Get the total number of bytes received through all network interfaces.
333     *
334     * @return number of bytes.  If the statistics are not supported by this device,
335     * {@link #UNSUPPORTED} will be returned.
336     */
337    public static native long getTotalRxBytes();
338
339    /**
340     * Get the number of bytes sent through the network for this UID.
341     * The statistics are across all interfaces.
342     *
343     * {@see android.os.Process#myUid()}.
344     *
345     * @param uid The UID of the process to examine.
346     * @return number of bytes.  If the statistics are not supported by this device,
347     * {@link #UNSUPPORTED} will be returned.
348     */
349    public static native long getUidTxBytes(int uid);
350
351    /**
352     * Get the number of bytes received through the network for this UID.
353     * The statistics are across all interfaces.
354     *
355     * {@see android.os.Process#myUid()}.
356     *
357     * @param uid The UID of the process to examine.
358     * @return number of bytes
359     */
360    public static native long getUidRxBytes(int uid);
361
362    /**
363     * Get the number of packets (TCP segments + UDP) sent through
364     * the network for this UID.
365     * The statistics are across all interfaces.
366     *
367     * {@see android.os.Process#myUid()}.
368     *
369     * @param uid The UID of the process to examine.
370     * @return number of packets.
371     * If the statistics are not supported by this device,
372     * {@link #UNSUPPORTED} will be returned.
373     */
374    public static native long getUidTxPackets(int uid);
375
376    /**
377     * Get the number of packets (TCP segments + UDP) received through
378     * the network for this UID.
379     * The statistics are across all interfaces.
380     *
381     * {@see android.os.Process#myUid()}.
382     *
383     * @param uid The UID of the process to examine.
384     * @return number of packets
385     */
386    public static native long getUidRxPackets(int uid);
387
388    /**
389     * Get the number of TCP payload bytes sent for this UID.
390     * This total does not include protocol and control overheads at
391     * the transport and the lower layers of the networking stack.
392     * The statistics are across all interfaces.
393     *
394     * {@see android.os.Process#myUid()}.
395     *
396     * @param uid The UID of the process to examine.
397     * @return number of bytes.  If the statistics are not supported by this device,
398     * {@link #UNSUPPORTED} will be returned.
399     */
400    public static native long getUidTcpTxBytes(int uid);
401
402    /**
403     * Get the number of TCP payload bytes received for this UID.
404     * This total does not include protocol and control overheads at
405     * the transport and the lower layers of the networking stack.
406     * The statistics are across all interfaces.
407     *
408     * {@see android.os.Process#myUid()}.
409     *
410     * @param uid The UID of the process to examine.
411     * @return number of bytes.  If the statistics are not supported by this device,
412     * {@link #UNSUPPORTED} will be returned.
413     */
414    public static native long getUidTcpRxBytes(int uid);
415
416    /**
417     * Get the number of UDP payload bytes sent for this UID.
418     * This total does not include protocol and control overheads at
419     * the transport and the lower layers of the networking stack.
420     * The statistics are across all interfaces.
421     *
422     * {@see android.os.Process#myUid()}.
423     *
424     * @param uid The UID of the process to examine.
425     * @return number of bytes.  If the statistics are not supported by this device,
426     * {@link #UNSUPPORTED} will be returned.
427     */
428    public static native long getUidUdpTxBytes(int uid);
429
430    /**
431     * Get the number of UDP payload bytes received for this UID.
432     * This total does not include protocol and control overheads at
433     * the transport and the lower layers of the networking stack.
434     * The statistics are across all interfaces.
435     *
436     * {@see android.os.Process#myUid()}.
437     *
438     * @param uid The UID of the process to examine.
439     * @return number of bytes.  If the statistics are not supported by this device,
440     * {@link #UNSUPPORTED} will be returned.
441     */
442    public static native long getUidUdpRxBytes(int uid);
443
444    /**
445     * Get the number of TCP segments sent for this UID.
446     * Does not include TCP control packets (SYN/ACKs/FIN/..).
447     * The statistics are across all interfaces.
448     *
449     * {@see android.os.Process#myUid()}.
450     *
451     * @param uid The UID of the process to examine.
452     * @return number of TCP segments.  If the statistics are not supported by this device,
453     * {@link #UNSUPPORTED} will be returned.
454     */
455    public static native long getUidTcpTxSegments(int uid);
456
457    /**
458     * Get the number of TCP segments received for this UID.
459     * Does not include TCP control packets (SYN/ACKs/FIN/..).
460     * The statistics are across all interfaces.
461     *
462     * {@see android.os.Process#myUid()}.
463     *
464     * @param uid The UID of the process to examine.
465     * @return number of TCP segments.  If the statistics are not supported by this device,
466     * {@link #UNSUPPORTED} will be returned.
467     */
468    public static native long getUidTcpRxSegments(int uid);
469
470
471    /**
472     * Get the number of UDP packets sent for this UID.
473     * Includes DNS requests.
474     * The statistics are across all interfaces.
475     *
476     * {@see android.os.Process#myUid()}.
477     *
478     * @param uid The UID of the process to examine.
479     * @return number of packets.  If the statistics are not supported by this device,
480     * {@link #UNSUPPORTED} will be returned.
481     */
482    public static native long getUidUdpTxPackets(int uid);
483
484    /**
485     * Get the number of UDP packets received for this UID.
486     * Includes DNS responses.
487     * The statistics are across all interfaces.
488     *
489     * {@see android.os.Process#myUid()}.
490     *
491     * @param uid The UID of the process to examine.
492     * @return number of packets.  If the statistics are not supported by this device,
493     * {@link #UNSUPPORTED} will be returned.
494     */
495    public static native long getUidUdpRxPackets(int uid);
496
497    /**
498     * Return detailed {@link NetworkStats} for the current UID. Requires no
499     * special permission.
500     */
501    private static NetworkStats getDataLayerSnapshotForUid(Context context) {
502        final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
503                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
504        final int uid = android.os.Process.myUid();
505        try {
506            return statsService.getDataLayerSnapshotForUid(uid);
507        } catch (RemoteException e) {
508            throw new RuntimeException(e);
509        }
510    }
511}
512