blob: 7961a72a12e441638b013530afb248c145d7ed12 [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
Jeff Davidsona6a78072016-01-11 16:02:17 -080054 * bucket for a particular key and state and roaming combination. In case of the user-wide and
55 * 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 />
Jeff Davidsona6a78072016-01-11 16:02:17 -080061 * These queries do not aggregate over time but do aggregate over state and roaming. Therefore there
62 * can be multiple buckets for a particular key but all Bucket's state is going to be
63 * {@link NetworkStats.Bucket#STATE_ALL} and all Bucket's roaming is going to be
64 * {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000065 * <p />
Zoltan Szatmary-Ban3a8b3432016-01-21 10:44:37 +000066 * <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
67 * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
68 * which is a system-level permission and will not be granted to third-party apps. However,
69 * declaring the permission implies intention to use the API and the user of the device can grant
70 * permission through the Settings application.
71 * <p />
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000072 * Profile owner apps are automatically granted permission to query data on the profile they manage
Jeff Davidson1efb1332015-12-09 18:04:50 -080073 * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
74 * privileged apps likewise get access to usage data for all users on the device.
75 * <p />
76 * In addition to tethering usage, usage by removed users and apps, and usage by the system
77 * is also included in the results for callers with one of these higher levels of access.
78 * <p />
79 * <b>NOTE:</b> Prior to API level {@value Build.VERSION_CODES#N}, all calls to these APIs required
80 * the above permission, even to access an app's own data usage, and carrier-privileged apps were
81 * not included.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000082 */
83public class NetworkStatsManager {
Antonio Cansadocd42acd2016-02-17 13:03:38 -080084 private static final String TAG = "NetworkStatsManager";
85 private static final boolean DBG = false;
86
87 /** @hide */
88 public static final int CALLBACK_LIMIT_REACHED = 0;
89 /** @hide */
90 public static final int CALLBACK_RELEASED = 1;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000091
92 private final Context mContext;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080093 private final INetworkStatsService mService;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000094
95 /**
96 * {@hide}
97 */
98 public NetworkStatsManager(Context context) {
99 mContext = context;
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800100 mService = INetworkStatsService.Stub.asInterface(
101 ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000102 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800103
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000104 /**
105 * Query network usage statistics summaries. Result is summarised data usage for the whole
Antonio Cansado46c753672015-12-10 15:57:56 -0800106 * device. Result is a single Bucket aggregated over time, state, uid, tag and roaming. This
107 * means the bucket's start and end timestamp are going to be the same as the 'startTime' and
108 * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid
Antonio Cansado6965c182016-03-30 11:37:18 -0700109 * {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE}
Antonio Cansado46c753672015-12-10 15:57:56 -0800110 * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000111 *
112 * @param networkType As defined in {@link ConnectivityManager}, e.g.
113 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
114 * etc.
115 * @param subscriberId If applicable, the subscriber id of the network interface.
116 * @param startTime Start of period. Defined in terms of "Unix time", see
117 * {@link java.lang.System#currentTimeMillis}.
118 * @param endTime End of period. Defined in terms of "Unix time", see
119 * {@link java.lang.System#currentTimeMillis}.
120 * @return Bucket object or null if permissions are insufficient or error happened during
121 * statistics collection.
122 */
123 public Bucket querySummaryForDevice(int networkType, String subscriberId,
124 long startTime, long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700125 NetworkTemplate template;
126 try {
127 template = createTemplate(networkType, subscriberId);
128 } catch (IllegalArgumentException e) {
129 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000130 return null;
131 }
132
133 Bucket bucket = null;
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100134 NetworkStats stats = new NetworkStats(mContext, template, startTime, endTime);
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100135 bucket = stats.getDeviceSummaryForNetwork();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000136
137 stats.close();
138 return bucket;
139 }
140
141 /**
142 * Query network usage statistics summaries. Result is summarised data usage for all uids
143 * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100144 * This means the bucket's start and end timestamp are going to be the same as the 'startTime'
Antonio Cansado6965c182016-03-30 11:37:18 -0700145 * and 'endTime' parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid
Antonio Cansado46c753672015-12-10 15:57:56 -0800146 * {@link NetworkStats.Bucket#UID_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000147 *
148 * @param networkType As defined in {@link ConnectivityManager}, e.g.
149 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
150 * etc.
151 * @param subscriberId If applicable, the subscriber id of the network interface.
152 * @param startTime Start of period. Defined in terms of "Unix time", see
153 * {@link java.lang.System#currentTimeMillis}.
154 * @param endTime End of period. Defined in terms of "Unix time", see
155 * {@link java.lang.System#currentTimeMillis}.
156 * @return Bucket object or null if permissions are insufficient or error happened during
157 * statistics collection.
158 */
159 public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700160 long endTime) throws SecurityException, RemoteException {
161 NetworkTemplate template;
162 try {
163 template = createTemplate(networkType, subscriberId);
164 } catch (IllegalArgumentException e) {
165 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000166 return null;
167 }
168
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100169 NetworkStats stats;
170 stats = new NetworkStats(mContext, template, startTime, endTime);
Antonio Cansado6965c182016-03-30 11:37:18 -0700171 stats.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000172
173 stats.close();
174 return stats.getSummaryAggregate();
175 }
176
177 /**
178 * Query network usage statistics summaries. Result filtered to include only uids belonging to
179 * calling user. Result is aggregated over time, hence all buckets will have the same start and
Antonio Cansado6965c182016-03-30 11:37:18 -0700180 * end timestamps. Not aggregated over state or uid. This means buckets' start and end
181 * timestamps are going to be the same as the 'startTime' and 'endTime' parameters.
182 * State and uid are going to vary, and tag is going to be the same.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000183 *
184 * @param networkType As defined in {@link ConnectivityManager}, e.g.
185 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
186 * etc.
187 * @param subscriberId If applicable, the subscriber id of the network interface.
188 * @param startTime Start of period. Defined in terms of "Unix time", see
189 * {@link java.lang.System#currentTimeMillis}.
190 * @param endTime End of period. Defined in terms of "Unix time", see
191 * {@link java.lang.System#currentTimeMillis}.
192 * @return Statistics object or null if permissions are insufficient or error happened during
193 * statistics collection.
194 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100195 public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700196 long endTime) throws SecurityException, RemoteException {
197 NetworkTemplate template;
198 try {
199 template = createTemplate(networkType, subscriberId);
200 } catch (IllegalArgumentException e) {
201 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000202 return null;
203 }
204
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100205 NetworkStats result;
206 result = new NetworkStats(mContext, template, startTime, endTime);
Antonio Cansado6965c182016-03-30 11:37:18 -0700207 result.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000208
209 return result;
210 }
211
212 /**
Antonio Cansado46c753672015-12-10 15:57:56 -0800213 * Query network usage statistics details for a given uid.
214 *
215 * #see queryDetailsForUidTag(int, String, long, long, int, int)
216 */
217 public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
218 long startTime, long endTime, int uid) throws SecurityException, RemoteException {
219 return queryDetailsForUidTag(networkType, subscriberId, startTime, endTime, uid,
Antonio Cansado6965c182016-03-30 11:37:18 -0700220 NetworkStats.Bucket.TAG_NONE);
Antonio Cansado46c753672015-12-10 15:57:56 -0800221 }
222
223 /**
224 * Query network usage statistics details for a given uid and tag. Only usable for uids
225 * belonging to calling user. Result is aggregated over state but not aggregated over time.
226 * This means buckets' start and end timestamps are going to be between 'startTime' and
227 * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid the
228 * same as the 'uid' parameter and tag the same as 'tag' parameter.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100229 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
230 * interpolate across partial buckets. Since bucket length is in the order of hours, this
231 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000232 *
233 * @param networkType As defined in {@link ConnectivityManager}, e.g.
234 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
235 * etc.
236 * @param subscriberId If applicable, the subscriber id of the network interface.
237 * @param startTime Start of period. Defined in terms of "Unix time", see
238 * {@link java.lang.System#currentTimeMillis}.
239 * @param endTime End of period. Defined in terms of "Unix time", see
240 * {@link java.lang.System#currentTimeMillis}.
241 * @param uid UID of app
Antonio Cansado6965c182016-03-30 11:37:18 -0700242 * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
Antonio Cansado904237f2016-05-25 09:57:21 -0700243 * @return Statistics object or null if an error happened during statistics collection.
244 * @throws SecurityException if permissions are insufficient to read network statistics.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000245 */
Antonio Cansado46c753672015-12-10 15:57:56 -0800246 public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
Antonio Cansado904237f2016-05-25 09:57:21 -0700247 long startTime, long endTime, int uid, int tag) throws SecurityException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700248 NetworkTemplate template;
Antonio Cansado904237f2016-05-25 09:57:21 -0700249 template = createTemplate(networkType, subscriberId);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000250
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100251 NetworkStats result;
Antonio Cansado6965c182016-03-30 11:37:18 -0700252 try {
253 result = new NetworkStats(mContext, template, startTime, endTime);
254 result.startHistoryEnumeration(uid, tag);
255 } catch (RemoteException e) {
256 Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e);
257 return null;
258 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000259
260 return result;
261 }
262
263 /**
264 * Query network usage statistics details. Result filtered to include only uids belonging to
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100265 * calling user. Result is aggregated over state but not aggregated over time or uid. This means
266 * buckets' start and end timestamps are going to be between 'startTime' and 'endTime'
Antonio Cansado46c753672015-12-10 15:57:56 -0800267 * parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
Antonio Cansado6965c182016-03-30 11:37:18 -0700268 * tag {@link NetworkStats.Bucket#TAG_NONE} and roaming is going to be
Antonio Cansado46c753672015-12-10 15:57:56 -0800269 * {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100270 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
271 * interpolate across partial buckets. Since bucket length is in the order of hours, this
272 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000273 *
274 * @param networkType As defined in {@link ConnectivityManager}, e.g.
275 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
276 * etc.
277 * @param subscriberId If applicable, the subscriber id of the network interface.
278 * @param startTime Start of period. Defined in terms of "Unix time", see
279 * {@link java.lang.System#currentTimeMillis}.
280 * @param endTime End of period. Defined in terms of "Unix time", see
281 * {@link java.lang.System#currentTimeMillis}.
282 * @return Statistics object or null if permissions are insufficient or error happened during
283 * statistics collection.
284 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100285 public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000286 long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700287 NetworkTemplate template;
288 try {
289 template = createTemplate(networkType, subscriberId);
290 } catch (IllegalArgumentException e) {
291 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000292 return null;
293 }
Antonio Cansado6965c182016-03-30 11:37:18 -0700294
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100295 NetworkStats result;
296 result = new NetworkStats(mContext, template, startTime, endTime);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000297 result.startUserUidEnumeration();
298 return result;
299 }
300
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800301 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700302 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800303 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700304 * #see registerUsageCallback(int, String[], long, UsageCallback, Handler)
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800305 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700306 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
307 UsageCallback callback) {
Antonio Cansadof7048372016-06-20 15:03:03 -0700308 registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
309 null /* handler */);
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800310 }
311
312 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700313 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800314 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700315 * <p>The callbacks will continue to be called as long as the process is live or
316 * {@link #unregisterUsageCallback} is called.
317 *
318 * @param networkType Type of network to monitor. Either
319 {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
320 * @param subscriberId If applicable, the subscriber id of the network interface.
321 * @param thresholdBytes Threshold in bytes to be notified on.
322 * @param callback The {@link UsageCallback} that the system will call when data usage
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800323 * has exceeded the specified threshold.
324 * @param handler to dispatch callback events through, otherwise if {@code null} it uses
325 * the calling thread.
326 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700327 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
328 UsageCallback callback, @Nullable Handler handler) {
329 checkNotNull(callback, "UsageCallback cannot be null");
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800330
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800331 final Looper looper;
332 if (handler == null) {
333 looper = Looper.myLooper();
334 } else {
335 looper = handler.getLooper();
336 }
337
Antonio Cansado6965c182016-03-30 11:37:18 -0700338 if (DBG) {
339 Log.d(TAG, "registerUsageCallback called with: {"
340 + " networkType=" + networkType
341 + " subscriberId=" + subscriberId
342 + " thresholdBytes=" + thresholdBytes
343 + " }");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800344 }
Antonio Cansado6965c182016-03-30 11:37:18 -0700345
346 NetworkTemplate template = createTemplate(networkType, subscriberId);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800347 DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
Antonio Cansado6965c182016-03-30 11:37:18 -0700348 template, thresholdBytes);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800349 try {
Antonio Cansado6965c182016-03-30 11:37:18 -0700350 CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
351 subscriberId, callback);
352 callback.request = mService.registerUsageCallback(
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800353 mContext.getOpPackageName(), request, new Messenger(callbackHandler),
354 new Binder());
Antonio Cansado6965c182016-03-30 11:37:18 -0700355 if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800356
357 if (callback.request == null) {
358 Log.e(TAG, "Request from callback is null; should not happen");
359 }
360 } catch (RemoteException e) {
361 if (DBG) Log.d(TAG, "Remote exception when registering callback");
Antonio Cansado6965c182016-03-30 11:37:18 -0700362 throw e.rethrowFromSystemServer();
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800363 }
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800364 }
365
366 /**
367 * Unregisters callbacks on data usage.
368 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700369 * @param callback The {@link UsageCallback} used when registering.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800370 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700371 public void unregisterUsageCallback(UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800372 if (callback == null || callback.request == null
373 || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700374 throw new IllegalArgumentException("Invalid UsageCallback");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800375 }
376 try {
Antonio Cansado6965c182016-03-30 11:37:18 -0700377 mService.unregisterUsageRequest(callback.request);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800378 } catch (RemoteException e) {
379 if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
Antonio Cansado6965c182016-03-30 11:37:18 -0700380 throw e.rethrowFromSystemServer();
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800381 }
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800382 }
383
Antonio Cansado6965c182016-03-30 11:37:18 -0700384 /**
385 * Base class for usage callbacks. Should be extended by applications wanting notifications.
386 */
387 public static abstract class UsageCallback {
388
389 /**
390 * Called when data usage has reached the given threshold.
391 */
392 public abstract void onThresholdReached(int networkType, String subscriberId);
393
394 /**
395 * @hide used for internal bookkeeping
396 */
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800397 private DataUsageRequest request;
398 }
399
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000400 private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
401 NetworkTemplate template = null;
402 switch (networkType) {
403 case ConnectivityManager.TYPE_MOBILE: {
404 template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
405 } break;
406 case ConnectivityManager.TYPE_WIFI: {
407 template = NetworkTemplate.buildTemplateWifiWildcard();
408 } break;
409 default: {
Antonio Cansado6965c182016-03-30 11:37:18 -0700410 throw new IllegalArgumentException("Cannot create template for network type "
411 + networkType + ", subscriberId '"
412 + NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000413 }
414 }
415 return template;
416 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800417
418 private static class CallbackHandler extends Handler {
Antonio Cansado6965c182016-03-30 11:37:18 -0700419 private final int mNetworkType;
420 private final String mSubscriberId;
421 private UsageCallback mCallback;
422
423 CallbackHandler(Looper looper, int networkType, String subscriberId,
424 UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800425 super(looper);
Antonio Cansado6965c182016-03-30 11:37:18 -0700426 mNetworkType = networkType;
427 mSubscriberId = subscriberId;
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800428 mCallback = callback;
429 }
430
431 @Override
432 public void handleMessage(Message message) {
433 DataUsageRequest request =
434 (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY);
435
436 switch (message.what) {
437 case CALLBACK_LIMIT_REACHED: {
438 if (mCallback != null) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700439 mCallback.onThresholdReached(mNetworkType, mSubscriberId);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800440 } else {
441 Log.e(TAG, "limit reached with released callback for " + request);
442 }
443 break;
444 }
445 case CALLBACK_RELEASED: {
446 if (DBG) Log.d(TAG, "callback released for " + request);
447 mCallback = null;
448 break;
449 }
450 }
451 }
452
453 private static Object getObject(Message msg, String key) {
454 return msg.getData().getParcelable(key);
455 }
456 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000457}