1/*
2 * Copyright (C) 2012 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.support.v4.net;
18
19import android.support.annotation.RequiresApi;
20import android.net.TrafficStats;
21import android.os.Build;
22import android.os.ParcelFileDescriptor;
23
24import java.net.DatagramSocket;
25import java.net.Socket;
26import java.net.SocketException;
27
28/**
29 * Helper for accessing features in {@link TrafficStats} introduced after API level 14
30 * in a backwards compatible fashion.
31 */
32public final class TrafficStatsCompat {
33    static class TrafficStatsCompatBaseImpl {
34        public void tagDatagramSocket(DatagramSocket socket) throws SocketException {
35            final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket);
36            TrafficStats.tagSocket(new DatagramSocketWrapper(socket, pfd.getFileDescriptor()));
37            // The developer is still using the FD, so we need to detach it to
38            // prevent the PFD finalizer from closing it in their face. We had to
39            // wait until after the tagging call above, since detaching clears out
40            // the getFileDescriptor() result which tagging depends on.
41            pfd.detachFd();
42        }
43
44        public void untagDatagramSocket(DatagramSocket socket) throws SocketException {
45            final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket);
46            TrafficStats.untagSocket(new DatagramSocketWrapper(socket, pfd.getFileDescriptor()));
47            // The developer is still using the FD, so we need to detach it to
48            // prevent the PFD finalizer from closing it in their face. We had to
49            // wait until after the tagging call above, since detaching clears out
50            // the getFileDescriptor() result which tagging depends on.
51            pfd.detachFd();
52        }
53    }
54
55    @RequiresApi(24)
56    static class TrafficStatsCompatApi24Impl extends TrafficStatsCompatBaseImpl {
57        @Override
58        public void tagDatagramSocket(DatagramSocket socket) throws SocketException {
59            TrafficStats.tagDatagramSocket(socket);
60        }
61
62        @Override
63        public void untagDatagramSocket(DatagramSocket socket) throws SocketException {
64            TrafficStats.untagDatagramSocket(socket);
65        }
66    }
67
68    private static final TrafficStatsCompatBaseImpl IMPL;
69
70    static {
71        if (Build.VERSION.SDK_INT >= 24) {
72            IMPL = new TrafficStatsCompatApi24Impl();
73        } else {
74            IMPL = new TrafficStatsCompatBaseImpl();
75        }
76    }
77
78    /**
79     * Clear active tag used when accounting {@link Socket} traffic originating
80     * from the current thread.
81     *
82     * @deprecated Use {@link TrafficStats#clearThreadStatsTag()} directly.
83     */
84    @Deprecated
85    public static void clearThreadStatsTag() {
86        TrafficStats.clearThreadStatsTag();
87    }
88
89    /**
90     * Get the active tag used when accounting {@link Socket} traffic originating
91     * from the current thread. Only one active tag per thread is supported.
92     * {@link #tagSocket(Socket)}.
93     *
94     * @deprecated Use {@link TrafficStats#getThreadStatsTag()} directly.
95     */
96    @Deprecated
97    public static int getThreadStatsTag() {
98        return TrafficStats.getThreadStatsTag();
99    }
100
101    /**
102     * Increment count of network operations performed under the accounting tag
103     * currently active on the calling thread. This can be used to derive
104     * bytes-per-operation.
105     *
106     * @param operationCount Number of operations to increment count by.
107     *
108     * @deprecated Use {@link TrafficStats#incrementOperationCount(int)} directly.
109     */
110    @Deprecated
111    public static void incrementOperationCount(int operationCount) {
112        TrafficStats.incrementOperationCount(operationCount);
113    }
114
115    /**
116     * Increment count of network operations performed under the given
117     * accounting tag. This can be used to derive bytes-per-operation.
118     *
119     * @param tag Accounting tag used in {@link #setThreadStatsTag(int)}.
120     * @param operationCount Number of operations to increment count by.
121     *
122     * @deprecated Use {@link TrafficStats#incrementOperationCount(int, int)} directly.
123     */
124    @Deprecated
125    public static void incrementOperationCount(int tag, int operationCount) {
126        TrafficStats.incrementOperationCount(tag, operationCount);
127    }
128
129    /**
130     * Set active tag to use when accounting {@link Socket} traffic originating
131     * from the current thread. Only one active tag per thread is supported.
132     * <p>
133     * Changes only take effect during subsequent calls to
134     * {@link #tagSocket(Socket)}.
135     * <p>
136     * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
137     * used internally by system services like DownloadManager when performing
138     * traffic on behalf of an application.
139     *
140     * @deprecated Use {@link TrafficStats#setThreadStatsTag(int)} directly.
141     */
142    @Deprecated
143    public static void setThreadStatsTag(int tag) {
144        TrafficStats.setThreadStatsTag(tag);
145    }
146
147    /**
148     * Tag the given {@link Socket} with any statistics parameters active for
149     * the current thread. Subsequent calls always replace any existing
150     * parameters. When finished, call {@link #untagSocket(Socket)} to remove
151     * statistics parameters.
152     *
153     * @see #setThreadStatsTag(int)
154     *
155     * @deprecated Use {@link TrafficStats#tagSocket(Socket)} directly.
156     */
157    @Deprecated
158    public static void tagSocket(Socket socket) throws SocketException {
159        TrafficStats.tagSocket(socket);
160    }
161
162    /**
163     * Remove any statistics parameters from the given {@link Socket}.
164     *
165     * @deprecated Use {@link TrafficStats#untagSocket(Socket)} directly.
166     */
167    @Deprecated
168    public static void untagSocket(Socket socket) throws SocketException {
169        TrafficStats.untagSocket(socket);
170    }
171
172    /**
173     * Tag the given {@link DatagramSocket} with any statistics parameters
174     * active for the current thread. Subsequent calls always replace any
175     * existing parameters. When finished, call
176     * {@link #untagDatagramSocket(DatagramSocket)} to remove statistics
177     * parameters.
178     *
179     * @see #setThreadStatsTag(int)
180     */
181    public static void tagDatagramSocket(DatagramSocket socket) throws SocketException {
182        IMPL.tagDatagramSocket(socket);
183    }
184
185    /**
186     * Remove any statistics parameters from the given {@link DatagramSocket}.
187     */
188    public static void untagDatagramSocket(DatagramSocket socket) throws SocketException {
189        IMPL.untagDatagramSocket(socket);
190    }
191
192    private TrafficStatsCompat() {}
193}
194