blob: 840413a1151e8e422e73fcc02708b9ab865d99cb [file] [log] [blame]
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +00001/**
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
Antonio Cansadoba8288d2015-12-02 08:42:54 -080019import static com.android.internal.util.Preconditions.checkNotNull;
20
21import android.annotation.Nullable;
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010022import android.app.usage.NetworkStats.Bucket;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000023import android.content.Context;
24import android.net.ConnectivityManager;
Antonio Cansadoba8288d2015-12-02 08:42:54 -080025import android.net.DataUsageRequest;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000026import android.net.NetworkIdentity;
27import android.net.NetworkTemplate;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080028import android.net.INetworkStatsService;
29import android.os.Binder;
Jeff Davidson1efb1332015-12-09 18:04:50 -080030import android.os.Build;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080031import android.os.Message;
32import android.os.Messenger;
Antonio Cansadoba8288d2015-12-02 08:42:54 -080033import android.os.Handler;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080034import android.os.Looper;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000035import android.os.RemoteException;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080036import android.os.ServiceManager;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000037import android.util.Log;
38
39/**
40 * Provides access to network usage history and statistics. Usage data is collected in
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010041 * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000042 * <p />
43 * Queries can define a time interval in the form of start and end timestamps (Long.MIN_VALUE and
Jeff Davidson1efb1332015-12-09 18:04:50 -080044 * Long.MAX_VALUE can be used to simulate open ended intervals). By default, apps can only obtain
45 * data about themselves. See the below note for special cases in which apps can obtain data about
46 * other applications.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000047 * <h3>
48 * Summary queries
49 * </h3>
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010050 * {@link #querySummaryForDevice} <p />
51 * {@link #querySummaryForUser} <p />
52 * {@link #querySummary} <p />
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000053 * These queries aggregate network usage across the whole interval. Therefore there will be only one
Stephen Chenc926b732016-10-21 12:44:26 -070054 * bucket for a particular key, state, metered and roaming combination. In case of the user-wide
55 * and device-wide summaries a single bucket containing the totalised network usage is returned.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000056 * <h3>
57 * History queries
58 * </h3>
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010059 * {@link #queryDetailsForUid} <p />
60 * {@link #queryDetails} <p />
Stephen Chenc926b732016-10-21 12:44:26 -070061 * These queries do not aggregate over time but do aggregate over state, metered and roaming.
62 * Therefore there can be multiple buckets for a particular key but all Bucket's state is going to
63 * be {@link NetworkStats.Bucket#STATE_ALL}, all Bucket's metered is going to be
64 * {@link NetworkStats.Bucket#METERED_ALL}, and all Bucket's roaming is going to be
Jeff Davidsona6a78072016-01-11 16:02:17 -080065 * {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000066 * <p />
Zoltan Szatmary-Ban3a8b3432016-01-21 10:44:37 +000067 * <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
68 * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
69 * which is a system-level permission and will not be granted to third-party apps. However,
70 * declaring the permission implies intention to use the API and the user of the device can grant
71 * permission through the Settings application.
72 * <p />
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000073 * Profile owner apps are automatically granted permission to query data on the profile they manage
Jeff Davidson1efb1332015-12-09 18:04:50 -080074 * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
75 * privileged apps likewise get access to usage data for all users on the device.
76 * <p />
77 * In addition to tethering usage, usage by removed users and apps, and usage by the system
78 * is also included in the results for callers with one of these higher levels of access.
79 * <p />
80 * <b>NOTE:</b> Prior to API level {@value Build.VERSION_CODES#N}, all calls to these APIs required
81 * the above permission, even to access an app's own data usage, and carrier-privileged apps were
82 * not included.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000083 */
84public class NetworkStatsManager {
Antonio Cansadocd42acd2016-02-17 13:03:38 -080085 private static final String TAG = "NetworkStatsManager";
86 private static final boolean DBG = false;
87
88 /** @hide */
89 public static final int CALLBACK_LIMIT_REACHED = 0;
90 /** @hide */
91 public static final int CALLBACK_RELEASED = 1;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000092
93 private final Context mContext;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080094 private final INetworkStatsService mService;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000095
96 /**
97 * {@hide}
98 */
99 public NetworkStatsManager(Context context) {
100 mContext = context;
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800101 mService = INetworkStatsService.Stub.asInterface(
102 ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000103 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800104
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000105 /**
106 * Query network usage statistics summaries. Result is summarised data usage for the whole
Stephen Chenc926b732016-10-21 12:44:26 -0700107 * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
108 * roaming. This means the bucket's start and end timestamp are going to be the same as the
109 * 'startTime' and 'endTime' parameters. State is going to be
110 * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL},
111 * tag {@link NetworkStats.Bucket#TAG_NONE}, metered {@link NetworkStats.Bucket#METERED_ALL},
Antonio Cansado46c753672015-12-10 15:57:56 -0800112 * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000113 *
114 * @param networkType As defined in {@link ConnectivityManager}, e.g.
115 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
116 * etc.
117 * @param subscriberId If applicable, the subscriber id of the network interface.
118 * @param startTime Start of period. Defined in terms of "Unix time", see
119 * {@link java.lang.System#currentTimeMillis}.
120 * @param endTime End of period. Defined in terms of "Unix time", see
121 * {@link java.lang.System#currentTimeMillis}.
122 * @return Bucket object or null if permissions are insufficient or error happened during
123 * statistics collection.
124 */
125 public Bucket querySummaryForDevice(int networkType, String subscriberId,
126 long startTime, long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700127 NetworkTemplate template;
128 try {
129 template = createTemplate(networkType, subscriberId);
130 } catch (IllegalArgumentException e) {
131 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000132 return null;
133 }
134
135 Bucket bucket = null;
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100136 NetworkStats stats = new NetworkStats(mContext, template, startTime, endTime);
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100137 bucket = stats.getDeviceSummaryForNetwork();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000138
139 stats.close();
140 return bucket;
141 }
142
143 /**
144 * Query network usage statistics summaries. Result is summarised data usage for all uids
145 * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100146 * This means the bucket's start and end timestamp are going to be the same as the 'startTime'
Stephen Chenc926b732016-10-21 12:44:26 -0700147 * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL},
148 * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE},
149 * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming
150 * {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000151 *
152 * @param networkType As defined in {@link ConnectivityManager}, e.g.
153 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
154 * etc.
155 * @param subscriberId If applicable, the subscriber id of the network interface.
156 * @param startTime Start of period. Defined in terms of "Unix time", see
157 * {@link java.lang.System#currentTimeMillis}.
158 * @param endTime End of period. Defined in terms of "Unix time", see
159 * {@link java.lang.System#currentTimeMillis}.
160 * @return Bucket object or null if permissions are insufficient or error happened during
161 * statistics collection.
162 */
163 public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700164 long endTime) throws SecurityException, RemoteException {
165 NetworkTemplate template;
166 try {
167 template = createTemplate(networkType, subscriberId);
168 } catch (IllegalArgumentException e) {
169 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000170 return null;
171 }
172
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100173 NetworkStats stats;
174 stats = new NetworkStats(mContext, template, startTime, endTime);
Antonio Cansado6965c182016-03-30 11:37:18 -0700175 stats.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000176
177 stats.close();
178 return stats.getSummaryAggregate();
179 }
180
181 /**
182 * Query network usage statistics summaries. Result filtered to include only uids belonging to
183 * calling user. Result is aggregated over time, hence all buckets will have the same start and
Stephen Chenc926b732016-10-21 12:44:26 -0700184 * end timestamps. State is going to be {@link NetworkStats.Bucket#STATE_ALL},
185 * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE},
186 * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming
187 * {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000188 *
189 * @param networkType As defined in {@link ConnectivityManager}, e.g.
190 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
191 * etc.
192 * @param subscriberId If applicable, the subscriber id of the network interface.
193 * @param startTime Start of period. Defined in terms of "Unix time", see
194 * {@link java.lang.System#currentTimeMillis}.
195 * @param endTime End of period. Defined in terms of "Unix time", see
196 * {@link java.lang.System#currentTimeMillis}.
197 * @return Statistics object or null if permissions are insufficient or error happened during
198 * statistics collection.
199 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100200 public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700201 long endTime) throws SecurityException, RemoteException {
202 NetworkTemplate template;
203 try {
204 template = createTemplate(networkType, subscriberId);
205 } catch (IllegalArgumentException e) {
206 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000207 return null;
208 }
209
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100210 NetworkStats result;
211 result = new NetworkStats(mContext, template, startTime, endTime);
Antonio Cansado6965c182016-03-30 11:37:18 -0700212 result.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000213
214 return result;
215 }
216
217 /**
Antonio Cansado46c753672015-12-10 15:57:56 -0800218 * Query network usage statistics details for a given uid.
219 *
220 * #see queryDetailsForUidTag(int, String, long, long, int, int)
221 */
222 public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
223 long startTime, long endTime, int uid) throws SecurityException, RemoteException {
224 return queryDetailsForUidTag(networkType, subscriberId, startTime, endTime, uid,
Antonio Cansado6965c182016-03-30 11:37:18 -0700225 NetworkStats.Bucket.TAG_NONE);
Antonio Cansado46c753672015-12-10 15:57:56 -0800226 }
227
228 /**
229 * Query network usage statistics details for a given uid and tag. Only usable for uids
230 * belonging to calling user. Result is aggregated over state but not aggregated over time.
231 * This means buckets' start and end timestamps are going to be between 'startTime' and
232 * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid the
233 * same as the 'uid' parameter and tag the same as 'tag' parameter.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100234 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
235 * interpolate across partial buckets. Since bucket length is in the order of hours, this
236 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000237 *
238 * @param networkType As defined in {@link ConnectivityManager}, e.g.
239 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
240 * etc.
241 * @param subscriberId If applicable, the subscriber id of the network interface.
242 * @param startTime Start of period. Defined in terms of "Unix time", see
243 * {@link java.lang.System#currentTimeMillis}.
244 * @param endTime End of period. Defined in terms of "Unix time", see
245 * {@link java.lang.System#currentTimeMillis}.
246 * @param uid UID of app
Antonio Cansado6965c182016-03-30 11:37:18 -0700247 * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
Antonio Cansado904237f2016-05-25 09:57:21 -0700248 * @return Statistics object or null if an error happened during statistics collection.
249 * @throws SecurityException if permissions are insufficient to read network statistics.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000250 */
Antonio Cansado46c753672015-12-10 15:57:56 -0800251 public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
Antonio Cansado904237f2016-05-25 09:57:21 -0700252 long startTime, long endTime, int uid, int tag) throws SecurityException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700253 NetworkTemplate template;
Antonio Cansado904237f2016-05-25 09:57:21 -0700254 template = createTemplate(networkType, subscriberId);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000255
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100256 NetworkStats result;
Antonio Cansado6965c182016-03-30 11:37:18 -0700257 try {
258 result = new NetworkStats(mContext, template, startTime, endTime);
259 result.startHistoryEnumeration(uid, tag);
260 } catch (RemoteException e) {
261 Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e);
262 return null;
263 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000264
265 return result;
266 }
267
268 /**
269 * Query network usage statistics details. Result filtered to include only uids belonging to
Stephen Chenc926b732016-10-21 12:44:26 -0700270 * calling user. Result is aggregated over state but not aggregated over time, uid, tag,
271 * metered, nor roaming. This means buckets' start and end timestamps are going to be between
272 * 'startTime' and 'endTime' parameters. State is going to be
273 * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
274 * tag {@link NetworkStats.Bucket#TAG_NONE}, metered is going to be
275 * {@link NetworkStats.Bucket#METERED_ALL}, and roaming is going to be
Antonio Cansado46c753672015-12-10 15:57:56 -0800276 * {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100277 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
278 * interpolate across partial buckets. Since bucket length is in the order of hours, this
279 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000280 *
281 * @param networkType As defined in {@link ConnectivityManager}, e.g.
282 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
283 * etc.
284 * @param subscriberId If applicable, the subscriber id of the network interface.
285 * @param startTime Start of period. Defined in terms of "Unix time", see
286 * {@link java.lang.System#currentTimeMillis}.
287 * @param endTime End of period. Defined in terms of "Unix time", see
288 * {@link java.lang.System#currentTimeMillis}.
289 * @return Statistics object or null if permissions are insufficient or error happened during
290 * statistics collection.
291 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100292 public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000293 long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700294 NetworkTemplate template;
295 try {
296 template = createTemplate(networkType, subscriberId);
297 } catch (IllegalArgumentException e) {
298 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000299 return null;
300 }
Antonio Cansado6965c182016-03-30 11:37:18 -0700301
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100302 NetworkStats result;
303 result = new NetworkStats(mContext, template, startTime, endTime);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000304 result.startUserUidEnumeration();
305 return result;
306 }
307
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800308 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700309 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800310 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700311 * #see registerUsageCallback(int, String[], long, UsageCallback, Handler)
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800312 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700313 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
314 UsageCallback callback) {
Antonio Cansadof7048372016-06-20 15:03:03 -0700315 registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
316 null /* handler */);
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800317 }
318
319 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700320 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800321 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700322 * <p>The callbacks will continue to be called as long as the process is live or
323 * {@link #unregisterUsageCallback} is called.
324 *
325 * @param networkType Type of network to monitor. Either
326 {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
327 * @param subscriberId If applicable, the subscriber id of the network interface.
328 * @param thresholdBytes Threshold in bytes to be notified on.
329 * @param callback The {@link UsageCallback} that the system will call when data usage
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800330 * has exceeded the specified threshold.
331 * @param handler to dispatch callback events through, otherwise if {@code null} it uses
332 * the calling thread.
333 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700334 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
335 UsageCallback callback, @Nullable Handler handler) {
336 checkNotNull(callback, "UsageCallback cannot be null");
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800337
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800338 final Looper looper;
339 if (handler == null) {
340 looper = Looper.myLooper();
341 } else {
342 looper = handler.getLooper();
343 }
344
Antonio Cansado6965c182016-03-30 11:37:18 -0700345 if (DBG) {
346 Log.d(TAG, "registerUsageCallback called with: {"
347 + " networkType=" + networkType
348 + " subscriberId=" + subscriberId
349 + " thresholdBytes=" + thresholdBytes
350 + " }");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800351 }
Antonio Cansado6965c182016-03-30 11:37:18 -0700352
353 NetworkTemplate template = createTemplate(networkType, subscriberId);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800354 DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
Antonio Cansado6965c182016-03-30 11:37:18 -0700355 template, thresholdBytes);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800356 try {
Antonio Cansado6965c182016-03-30 11:37:18 -0700357 CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
358 subscriberId, callback);
359 callback.request = mService.registerUsageCallback(
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800360 mContext.getOpPackageName(), request, new Messenger(callbackHandler),
361 new Binder());
Antonio Cansado6965c182016-03-30 11:37:18 -0700362 if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800363
364 if (callback.request == null) {
365 Log.e(TAG, "Request from callback is null; should not happen");
366 }
367 } catch (RemoteException e) {
368 if (DBG) Log.d(TAG, "Remote exception when registering callback");
Antonio Cansado6965c182016-03-30 11:37:18 -0700369 throw e.rethrowFromSystemServer();
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800370 }
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800371 }
372
373 /**
374 * Unregisters callbacks on data usage.
375 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700376 * @param callback The {@link UsageCallback} used when registering.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800377 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700378 public void unregisterUsageCallback(UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800379 if (callback == null || callback.request == null
380 || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700381 throw new IllegalArgumentException("Invalid UsageCallback");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800382 }
383 try {
Antonio Cansado6965c182016-03-30 11:37:18 -0700384 mService.unregisterUsageRequest(callback.request);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800385 } catch (RemoteException e) {
386 if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
Antonio Cansado6965c182016-03-30 11:37:18 -0700387 throw e.rethrowFromSystemServer();
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800388 }
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800389 }
390
Antonio Cansado6965c182016-03-30 11:37:18 -0700391 /**
392 * Base class for usage callbacks. Should be extended by applications wanting notifications.
393 */
394 public static abstract class UsageCallback {
395
396 /**
397 * Called when data usage has reached the given threshold.
398 */
399 public abstract void onThresholdReached(int networkType, String subscriberId);
400
401 /**
402 * @hide used for internal bookkeeping
403 */
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800404 private DataUsageRequest request;
405 }
406
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000407 private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
408 NetworkTemplate template = null;
409 switch (networkType) {
410 case ConnectivityManager.TYPE_MOBILE: {
411 template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
412 } break;
413 case ConnectivityManager.TYPE_WIFI: {
414 template = NetworkTemplate.buildTemplateWifiWildcard();
415 } break;
416 default: {
Antonio Cansado6965c182016-03-30 11:37:18 -0700417 throw new IllegalArgumentException("Cannot create template for network type "
418 + networkType + ", subscriberId '"
419 + NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000420 }
421 }
422 return template;
423 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800424
425 private static class CallbackHandler extends Handler {
Antonio Cansado6965c182016-03-30 11:37:18 -0700426 private final int mNetworkType;
427 private final String mSubscriberId;
428 private UsageCallback mCallback;
429
430 CallbackHandler(Looper looper, int networkType, String subscriberId,
431 UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800432 super(looper);
Antonio Cansado6965c182016-03-30 11:37:18 -0700433 mNetworkType = networkType;
434 mSubscriberId = subscriberId;
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800435 mCallback = callback;
436 }
437
438 @Override
439 public void handleMessage(Message message) {
440 DataUsageRequest request =
441 (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY);
442
443 switch (message.what) {
444 case CALLBACK_LIMIT_REACHED: {
445 if (mCallback != null) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700446 mCallback.onThresholdReached(mNetworkType, mSubscriberId);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800447 } else {
448 Log.e(TAG, "limit reached with released callback for " + request);
449 }
450 break;
451 }
452 case CALLBACK_RELEASED: {
453 if (DBG) Log.d(TAG, "callback released for " + request);
454 mCallback = null;
455 break;
456 }
457 }
458 }
459
460 private static Object getObject(Message msg, String key) {
461 return msg.getData().getParcelable(key);
462 }
463 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000464}