NetworkStatsManager.java revision 46c75367fa47bfd0429cab6121da0b897b5620a2
1/**
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16
17package android.app.usage;
18
19import android.app.usage.NetworkStats.Bucket;
20import android.content.Context;
21import android.net.ConnectivityManager;
22import android.net.NetworkIdentity;
23import android.net.NetworkTemplate;
24import android.os.Build;
25import android.os.RemoteException;
26import android.util.Log;
27
28/**
29 * Provides access to network usage history and statistics. Usage data is collected in
30 * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
31 * <p />
32 * Queries can define a time interval in the form of start and end timestamps (Long.MIN_VALUE and
33 * Long.MAX_VALUE can be used to simulate open ended intervals). By default, apps can only obtain
34 * data about themselves. See the below note for special cases in which apps can obtain data about
35 * other applications.
36 * <h3>
37 * Summary queries
38 * </h3>
39 * {@link #querySummaryForDevice} <p />
40 * {@link #querySummaryForUser} <p />
41 * {@link #querySummary} <p />
42 * These queries aggregate network usage across the whole interval. Therefore there will be only one
43 * bucket for a particular key and state and roaming combination. In case of the user-wide and
44 * device-wide summaries a single bucket containing the totalised network usage is returned.
45 * <h3>
46 * History queries
47 * </h3>
48 * {@link #queryDetailsForUid} <p />
49 * {@link #queryDetails} <p />
50 * These queries do not aggregate over time but do aggregate over state and roaming. Therefore there
51 * can be multiple buckets for a particular key but all Bucket's state is going to be
52 * {@link NetworkStats.Bucket#STATE_ALL} and all Bucket's roaming is going to be
53 * {@link NetworkStats.Bucket#ROAMING_ALL}.
54 * <p />
55 * <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
56 * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
57 * which is a system-level permission and will not be granted to third-party apps. However,
58 * declaring the permission implies intention to use the API and the user of the device can grant
59 * permission through the Settings application.
60 * <p />
61 * Profile owner apps are automatically granted permission to query data on the profile they manage
62 * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
63 * privileged apps likewise get access to usage data for all users on the device.
64 * <p />
65 * In addition to tethering usage, usage by removed users and apps, and usage by the system
66 * is also included in the results for callers with one of these higher levels of access.
67 * <p />
68 * <b>NOTE:</b> Prior to API level {@value Build.VERSION_CODES#N}, all calls to these APIs required
69 * the above permission, even to access an app's own data usage, and carrier-privileged apps were
70 * not included.
71 */
72public class NetworkStatsManager {
73    private final static String TAG = "NetworkStatsManager";
74
75    private final Context mContext;
76
77    /**
78     * {@hide}
79     */
80    public NetworkStatsManager(Context context) {
81        mContext = context;
82    }
83    /**
84     * Query network usage statistics summaries. Result is summarised data usage for the whole
85     * device. Result is a single Bucket aggregated over time, state, uid, tag and roaming. This
86     * means the bucket's start and end timestamp are going to be the same as the 'startTime' and
87     * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid
88     * {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_ALL}
89     * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
90     *
91     * @param networkType As defined in {@link ConnectivityManager}, e.g.
92     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
93     *            etc.
94     * @param subscriberId If applicable, the subscriber id of the network interface.
95     * @param startTime Start of period. Defined in terms of "Unix time", see
96     *            {@link java.lang.System#currentTimeMillis}.
97     * @param endTime End of period. Defined in terms of "Unix time", see
98     *            {@link java.lang.System#currentTimeMillis}.
99     * @return Bucket object or null if permissions are insufficient or error happened during
100     *         statistics collection.
101     */
102    public Bucket querySummaryForDevice(int networkType, String subscriberId,
103            long startTime, long endTime) throws SecurityException, RemoteException {
104        NetworkTemplate template = createTemplate(networkType, subscriberId);
105        if (template == null) {
106            return null;
107        }
108
109        Bucket bucket = null;
110        NetworkStats stats = new NetworkStats(mContext, template, startTime, endTime);
111        bucket = stats.getDeviceSummaryForNetwork();
112
113        stats.close();
114        return bucket;
115    }
116
117    /**
118     * Query network usage statistics summaries aggregated across tags.
119     *
120     * #see querySummaryForUser(int, String, long, long, boolean)
121     */
122    public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
123            long endTime) throws SecurityException, RemoteException {
124        return querySummaryForUser(networkType, subscriberId, startTime, endTime,
125            false /* includeTags */);
126    }
127
128    /**
129     * Query network usage statistics summaries. Result is summarised data usage for all uids
130     * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
131     * This means the bucket's start and end timestamp are going to be the same as the 'startTime'
132     * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid
133     * {@link NetworkStats.Bucket#UID_ALL}.
134     *
135     * @param networkType As defined in {@link ConnectivityManager}, e.g.
136     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
137     *            etc.
138     * @param subscriberId If applicable, the subscriber id of the network interface.
139     * @param startTime Start of period. Defined in terms of "Unix time", see
140     *            {@link java.lang.System#currentTimeMillis}.
141     * @param endTime End of period. Defined in terms of "Unix time", see
142     *            {@link java.lang.System#currentTimeMillis}.
143     * @param includeTags whether to include network tags. If {@code true}, tags will be returned
144     *            and history retention may be shorter.
145     * @return Bucket object or null if permissions are insufficient or error happened during
146     *         statistics collection.
147     */
148    public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
149            long endTime, boolean includeTags) throws SecurityException, RemoteException {
150        NetworkTemplate template = createTemplate(networkType, subscriberId);
151        if (template == null) {
152            return null;
153        }
154
155        NetworkStats stats;
156        stats = new NetworkStats(mContext, template, startTime, endTime);
157        stats.startSummaryEnumeration(includeTags);
158
159        stats.close();
160        return stats.getSummaryAggregate();
161    }
162
163    /**
164     * Query network usage statistics summaries aggregated across tags.
165     *
166     * #see querySummary(int, String, long, long, boolean)
167     */
168    public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
169            long endTime) throws SecurityException, RemoteException {
170        return querySummary(networkType, subscriberId, startTime, endTime, false /* includeTags */);
171    }
172
173    /**
174     * Query network usage statistics summaries. Result filtered to include only uids belonging to
175     * calling user. Result is aggregated over time, hence all buckets will have the same start and
176     * end timestamps. Not aggregated over state or uid or tag. This means buckets' start and end
177     * timestamps are going to be the same as the 'startTime' and 'endTime' parameters. State,
178     * uid and tag are going to vary.
179     *
180     * @param networkType As defined in {@link ConnectivityManager}, e.g.
181     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
182     *            etc.
183     * @param subscriberId If applicable, the subscriber id of the network interface.
184     * @param startTime Start of period. Defined in terms of "Unix time", see
185     *            {@link java.lang.System#currentTimeMillis}.
186     * @param endTime End of period. Defined in terms of "Unix time", see
187     *            {@link java.lang.System#currentTimeMillis}.
188     * @param includeTags whether to include network tags. If {@code true}, tags will be returned
189     *            and history retention may be shorter.
190     * @return Statistics object or null if permissions are insufficient or error happened during
191     *         statistics collection.
192     */
193    public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
194            long endTime, boolean includeTags) throws SecurityException, RemoteException {
195        NetworkTemplate template = createTemplate(networkType, subscriberId);
196        if (template == null) {
197            return null;
198        }
199
200        NetworkStats result;
201        result = new NetworkStats(mContext, template, startTime, endTime);
202        result.startSummaryEnumeration(includeTags);
203
204        return result;
205    }
206
207    /**
208     * Query network usage statistics details for a given uid.
209     *
210     * #see queryDetailsForUidTag(int, String, long, long, int, int)
211     */
212    public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
213            long startTime, long endTime, int uid) throws SecurityException, RemoteException {
214        return queryDetailsForUidTag(networkType, subscriberId, startTime, endTime, uid,
215            NetworkStats.Bucket.TAG_ALL);
216    }
217
218    /**
219     * Query network usage statistics details for a given uid and tag. Only usable for uids
220     * belonging to calling user. Result is aggregated over state but not aggregated over time.
221     * This means buckets' start and end timestamps are going to be between 'startTime' and
222     * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid the
223     * same as the 'uid' parameter and tag the same as 'tag' parameter.
224     * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
225     * interpolate across partial buckets. Since bucket length is in the order of hours, this
226     * method cannot be used to measure data usage on a fine grained time scale.
227     *
228     * @param networkType As defined in {@link ConnectivityManager}, e.g.
229     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
230     *            etc.
231     * @param subscriberId If applicable, the subscriber id of the network interface.
232     * @param startTime Start of period. Defined in terms of "Unix time", see
233     *            {@link java.lang.System#currentTimeMillis}.
234     * @param endTime End of period. Defined in terms of "Unix time", see
235     *            {@link java.lang.System#currentTimeMillis}.
236     * @param uid UID of app
237     * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_ANY} for any tags, use
238     *            {@link NetworkStats.Bucket#TAG_ALL} to aggregate over tags.
239     * @return Statistics object or null if permissions are insufficient or error happened during
240     *         statistics collection.
241     */
242    public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
243            long startTime, long endTime, int uid, int tag) throws SecurityException,
244            RemoteException {
245        NetworkTemplate template = createTemplate(networkType, subscriberId);
246        if (template == null) {
247            return null;
248        }
249
250        NetworkStats result;
251        result = new NetworkStats(mContext, template, startTime, endTime);
252        result.startHistoryEnumeration(uid, tag);
253
254        return result;
255    }
256
257    /**
258     * Query network usage statistics details. Result filtered to include only uids belonging to
259     * calling user. Result is aggregated over state but not aggregated over time or uid. This means
260     * buckets' start and end timestamps are going to be between 'startTime' and 'endTime'
261     * parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
262     * tag {@link NetworkStats.Bucket#TAG_ALL} and roaming is going to be
263     * {@link NetworkStats.Bucket#ROAMING_ALL}.
264     * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
265     * interpolate across partial buckets. Since bucket length is in the order of hours, this
266     * method cannot be used to measure data usage on a fine grained time scale.
267     *
268     * @param networkType As defined in {@link ConnectivityManager}, e.g.
269     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
270     *            etc.
271     * @param subscriberId If applicable, the subscriber id of the network interface.
272     * @param startTime Start of period. Defined in terms of "Unix time", see
273     *            {@link java.lang.System#currentTimeMillis}.
274     * @param endTime End of period. Defined in terms of "Unix time", see
275     *            {@link java.lang.System#currentTimeMillis}.
276     * @return Statistics object or null if permissions are insufficient or error happened during
277     *         statistics collection.
278     */
279    public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
280            long endTime) throws SecurityException, RemoteException {
281        NetworkTemplate template = createTemplate(networkType, subscriberId);
282        if (template == null) {
283            return null;
284        }
285        NetworkStats result;
286        result = new NetworkStats(mContext, template, startTime, endTime);
287        result.startUserUidEnumeration();
288        return result;
289    }
290
291    private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
292        NetworkTemplate template = null;
293        switch (networkType) {
294            case ConnectivityManager.TYPE_MOBILE: {
295                template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
296                } break;
297            case ConnectivityManager.TYPE_WIFI: {
298                template = NetworkTemplate.buildTemplateWifiWildcard();
299                } break;
300            default: {
301                Log.w(TAG, "Cannot create template for network type " + networkType
302                        + ", subscriberId '" + NetworkIdentity.scrubSubscriberId(subscriberId) +
303                        "'.");
304            }
305        }
306        return template;
307    }
308}
309