blob: 3670b914ecf378ccafd9ab9a452a4341103a562b [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
Jeff Davidson1f7e05e2016-03-10 13:21:38 -080019import android.annotation.IntDef;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000020import android.content.Context;
21import android.net.INetworkStatsService;
22import android.net.INetworkStatsSession;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000023import android.net.NetworkStatsHistory;
24import android.net.NetworkTemplate;
25import android.net.TrafficStats;
26import android.os.RemoteException;
27import android.os.ServiceManager;
Zoltan Szatmary-Ban887cffe2015-08-13 16:53:10 +010028import android.util.IntArray;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000029import android.util.Log;
30
31import dalvik.system.CloseGuard;
32
Jeff Davidson1f7e05e2016-03-10 13:21:38 -080033import java.lang.annotation.Retention;
34import java.lang.annotation.RetentionPolicy;
35
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000036/**
Zoltan Szatmary-Bandf70dce2015-06-04 14:07:55 +010037 * Class providing enumeration over buckets of network usage statistics. {@link NetworkStats} objects
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000038 * are returned as results to various queries in {@link NetworkStatsManager}.
39 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010040public final class NetworkStats implements AutoCloseable {
Zoltan Szatmary-Bandf70dce2015-06-04 14:07:55 +010041 private final static String TAG = "NetworkStats";
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000042
43 private final CloseGuard mCloseGuard = CloseGuard.get();
44
45 /**
46 * Start timestamp of stats collected
47 */
48 private final long mStartTimeStamp;
49
50 /**
51 * End timestamp of stats collected
52 */
53 private final long mEndTimeStamp;
54
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000055 /**
56 * Non-null array indicates the query enumerates over uids.
57 */
58 private int[] mUids;
59
60 /**
61 * Index of the current uid in mUids when doing uid enumeration or a single uid value,
62 * depending on query type.
63 */
64 private int mUidOrUidIndex;
65
66 /**
Antonio Cansado3e883da2016-04-22 11:23:27 -070067 * Tag id in case if was specified in the query.
68 */
69 private int mTag = android.net.NetworkStats.TAG_NONE;
70
71 /**
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000072 * The session while the query requires it, null if all the stats have been collected or close()
73 * has been called.
74 */
75 private INetworkStatsSession mSession;
76 private NetworkTemplate mTemplate;
77
78 /**
79 * Results of a summary query.
80 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010081 private android.net.NetworkStats mSummary = null;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000082
83 /**
84 * Results of detail queries.
85 */
86 private NetworkStatsHistory mHistory = null;
87
88 /**
89 * Where we are in enumerating over the current result.
90 */
91 private int mEnumerationIndex = 0;
92
93 /**
94 * Recycling entry objects to prevent heap fragmentation.
95 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010096 private android.net.NetworkStats.Entry mRecycledSummaryEntry = null;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000097 private NetworkStatsHistory.Entry mRecycledHistoryEntry = null;
98
99 /** @hide */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100100 NetworkStats(Context context, NetworkTemplate template, long startTimestamp,
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000101 long endTimestamp) throws RemoteException, SecurityException {
102 final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
103 ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
104 // Open network stats session
105 mSession = statsService.openSessionForUsageStats(context.getOpPackageName());
106 mCloseGuard.open("close");
107 mTemplate = template;
108 mStartTimeStamp = startTimestamp;
109 mEndTimeStamp = endTimestamp;
110 }
111
112 @Override
113 protected void finalize() throws Throwable {
114 try {
115 if (mCloseGuard != null) {
116 mCloseGuard.warnIfOpen();
117 }
118 close();
119 } finally {
120 super.finalize();
121 }
122 }
123
124 // -------------------------BEGINNING OF PUBLIC API-----------------------------------
125
126 /**
127 * Buckets are the smallest elements of a query result. As some dimensions of a result may be
128 * aggregated (e.g. time or state) some values may be equal across all buckets.
129 */
130 public static class Bucket {
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800131 /** @hide */
132 @IntDef({STATE_ALL, STATE_DEFAULT, STATE_FOREGROUND})
133 @Retention(RetentionPolicy.SOURCE)
134 public @interface State {}
135
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000136 /**
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800137 * Combined usage across all states.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000138 */
139 public static final int STATE_ALL = -1;
140
141 /**
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800142 * Usage not accounted for in any other state.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000143 */
144 public static final int STATE_DEFAULT = 0x1;
145
146 /**
147 * Foreground usage.
148 */
149 public static final int STATE_FOREGROUND = 0x2;
150
151 /**
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100152 * Special UID value for aggregate/unspecified.
153 */
154 public static final int UID_ALL = android.net.NetworkStats.UID_ALL;
155
156 /**
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000157 * Special UID value for removed apps.
158 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100159 public static final int UID_REMOVED = TrafficStats.UID_REMOVED;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000160
161 /**
162 * Special UID value for data usage by tethering.
163 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100164 public static final int UID_TETHERING = TrafficStats.UID_TETHERING;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000165
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800166 /** @hide */
Stephen Chen1fee3a62016-10-18 16:41:47 -0700167 @IntDef({METERED_ALL, METERED_NO, METERED_YES})
168 @Retention(RetentionPolicy.SOURCE)
169 public @interface Metered {}
170
171 /**
172 * Combined usage across all metered states. Covers metered and unmetered usage.
173 */
174 public static final int METERED_ALL = -1;
175
176 /**
177 * Usage that occurs on an unmetered network.
178 */
179 public static final int METERED_NO = 0x1;
180
181 /**
182 * Usage that occurs on a metered network.
183 *
184 * <p>A network is classified as metered when the user is sensitive to heavy data usage on
185 * that connection.
186 */
187 public static final int METERED_YES = 0x2;
188
189 /** @hide */
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800190 @IntDef({ROAMING_ALL, ROAMING_NO, ROAMING_YES})
191 @Retention(RetentionPolicy.SOURCE)
192 public @interface Roaming {}
193
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800194 /**
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800195 * Combined usage across all roaming states. Covers both roaming and non-roaming usage.
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800196 */
197 public static final int ROAMING_ALL = -1;
198
199 /**
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800200 * Usage that occurs on a home, non-roaming network.
201 *
202 * <p>Any cellular usage in this bucket was incurred while the device was connected to a
203 * tower owned or operated by the user's wireless carrier, or a tower that the user's
204 * wireless carrier has indicated should be treated as a home network regardless.
205 *
206 * <p>This is also the default value for network types that do not support roaming.
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800207 */
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800208 public static final int ROAMING_NO = 0x1;
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800209
210 /**
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800211 * Usage that occurs on a roaming network.
212 *
213 * <p>Any cellular usage in this bucket as incurred while the device was roaming on another
214 * carrier's network, for which additional charges may apply.
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800215 */
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800216 public static final int ROAMING_YES = 0x2;
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800217
Antonio Cansado46c753672015-12-10 15:57:56 -0800218 /**
Antonio Cansado46c753672015-12-10 15:57:56 -0800219 * Special TAG value for total data across all tags
220 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700221 public static final int TAG_NONE = android.net.NetworkStats.TAG_NONE;
Antonio Cansado46c753672015-12-10 15:57:56 -0800222
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000223 private int mUid;
Antonio Cansado46c753672015-12-10 15:57:56 -0800224 private int mTag;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000225 private int mState;
Stephen Chen1fee3a62016-10-18 16:41:47 -0700226 private int mMetered;
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800227 private int mRoaming;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000228 private long mBeginTimeStamp;
229 private long mEndTimeStamp;
230 private long mRxBytes;
231 private long mRxPackets;
232 private long mTxBytes;
233 private long mTxPackets;
234
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800235 private static @State int convertState(int networkStatsSet) {
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000236 switch (networkStatsSet) {
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100237 case android.net.NetworkStats.SET_ALL : return STATE_ALL;
238 case android.net.NetworkStats.SET_DEFAULT : return STATE_DEFAULT;
239 case android.net.NetworkStats.SET_FOREGROUND : return STATE_FOREGROUND;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000240 }
241 return 0;
242 }
243
244 private static int convertUid(int uid) {
245 switch (uid) {
246 case TrafficStats.UID_REMOVED: return UID_REMOVED;
247 case TrafficStats.UID_TETHERING: return UID_TETHERING;
248 }
249 return uid;
250 }
251
Antonio Cansado46c753672015-12-10 15:57:56 -0800252 private static int convertTag(int tag) {
253 switch (tag) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700254 case android.net.NetworkStats.TAG_NONE: return TAG_NONE;
Antonio Cansado46c753672015-12-10 15:57:56 -0800255 }
256 return tag;
257 }
258
Stephen Chenc926b732016-10-21 12:44:26 -0700259 private static @Metered int convertMetered(int metered) {
260 switch (metered) {
261 case android.net.NetworkStats.METERED_ALL : return METERED_ALL;
262 case android.net.NetworkStats.METERED_NO: return METERED_NO;
263 case android.net.NetworkStats.METERED_YES: return METERED_YES;
264 }
265 return 0;
266 }
267
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800268 private static @Roaming int convertRoaming(int roaming) {
Jeff Davidsona6a78072016-01-11 16:02:17 -0800269 switch (roaming) {
270 case android.net.NetworkStats.ROAMING_ALL : return ROAMING_ALL;
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800271 case android.net.NetworkStats.ROAMING_NO: return ROAMING_NO;
272 case android.net.NetworkStats.ROAMING_YES: return ROAMING_YES;
Jeff Davidsona6a78072016-01-11 16:02:17 -0800273 }
274 return 0;
275 }
276
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000277 public Bucket() {
278 }
279
280 /**
281 * Key of the bucket. Usually an app uid or one of the following special values:<p />
282 * <ul>
283 * <li>{@link #UID_REMOVED}</li>
284 * <li>{@link #UID_TETHERING}</li>
285 * <li>{@link android.os.Process#SYSTEM_UID}</li>
286 * </ul>
287 * @return Bucket key.
288 */
289 public int getUid() {
290 return mUid;
291 }
292
293 /**
Antonio Cansado46c753672015-12-10 15:57:56 -0800294 * Tag of the bucket.<p />
295 * @return Bucket tag.
296 */
297 public int getTag() {
298 return mTag;
299 }
300
301 /**
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000302 * Usage state. One of the following values:<p/>
303 * <ul>
304 * <li>{@link #STATE_ALL}</li>
305 * <li>{@link #STATE_DEFAULT}</li>
306 * <li>{@link #STATE_FOREGROUND}</li>
307 * </ul>
308 * @return Usage state.
309 */
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800310 public @State int getState() {
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000311 return mState;
312 }
313
314 /**
Stephen Chen1fee3a62016-10-18 16:41:47 -0700315 * Metered state. One of the following values:<p/>
316 * <ul>
317 * <li>{@link #METERED_ALL}</li>
318 * <li>{@link #METERED_NO}</li>
319 * <li>{@link #METERED_YES}</li>
320 * </ul>
321 * <p>A network is classified as metered when the user is sensitive to heavy data usage on
322 * that connection. Apps may warn before using these networks for large downloads. The
323 * metered state can be set by the user within data usage network restrictions.
324 */
325 public @Metered int getMetered() {
326 return mMetered;
327 }
328
329 /**
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800330 * Roaming state. One of the following values:<p/>
331 * <ul>
332 * <li>{@link #ROAMING_ALL}</li>
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800333 * <li>{@link #ROAMING_NO}</li>
334 * <li>{@link #ROAMING_YES}</li>
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800335 * </ul>
336 */
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800337 public @Roaming int getRoaming() {
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800338 return mRoaming;
339 }
340
341 /**
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000342 * Start timestamp of the bucket's time interval. Defined in terms of "Unix time", see
343 * {@link java.lang.System#currentTimeMillis}.
344 * @return Start of interval.
345 */
346 public long getStartTimeStamp() {
347 return mBeginTimeStamp;
348 }
349
350 /**
351 * End timestamp of the bucket's time interval. Defined in terms of "Unix time", see
352 * {@link java.lang.System#currentTimeMillis}.
353 * @return End of interval.
354 */
355 public long getEndTimeStamp() {
356 return mEndTimeStamp;
357 }
358
359 /**
360 * Number of bytes received during the bucket's time interval. Statistics are measured at
361 * the network layer, so they include both TCP and UDP usage.
362 * @return Number of bytes.
363 */
364 public long getRxBytes() {
365 return mRxBytes;
366 }
367
368 /**
369 * Number of bytes transmitted during the bucket's time interval. Statistics are measured at
370 * the network layer, so they include both TCP and UDP usage.
371 * @return Number of bytes.
372 */
373 public long getTxBytes() {
374 return mTxBytes;
375 }
376
377 /**
378 * Number of packets received during the bucket's time interval. Statistics are measured at
379 * the network layer, so they include both TCP and UDP usage.
380 * @return Number of packets.
381 */
382 public long getRxPackets() {
383 return mRxPackets;
384 }
385
386 /**
387 * Number of packets transmitted during the bucket's time interval. Statistics are measured
388 * at the network layer, so they include both TCP and UDP usage.
389 * @return Number of packets.
390 */
391 public long getTxPackets() {
392 return mTxPackets;
393 }
394 }
395
396 /**
397 * Fills the recycled bucket with data of the next bin in the enumeration.
398 * @param bucketOut Bucket to be filled with data.
399 * @return true if successfully filled the bucket, false otherwise.
400 */
401 public boolean getNextBucket(Bucket bucketOut) {
402 if (mSummary != null) {
403 return getNextSummaryBucket(bucketOut);
404 } else {
405 return getNextHistoryBucket(bucketOut);
406 }
407 }
408
409 /**
410 * Check if it is possible to ask for a next bucket in the enumeration.
411 * @return true if there is at least one more bucket.
412 */
413 public boolean hasNextBucket() {
414 if (mSummary != null) {
415 return mEnumerationIndex < mSummary.size();
416 } else if (mHistory != null) {
417 return mEnumerationIndex < mHistory.size()
418 || hasNextUid();
419 }
420 return false;
421 }
422
423 /**
424 * Closes the enumeration. Call this method before this object gets out of scope.
425 */
426 @Override
427 public void close() {
428 if (mSession != null) {
429 try {
430 mSession.close();
431 } catch (RemoteException e) {
432 Log.w(TAG, e);
433 // Otherwise, meh
434 }
435 }
436 mSession = null;
437 if (mCloseGuard != null) {
438 mCloseGuard.close();
439 }
440 }
441
442 // -------------------------END OF PUBLIC API-----------------------------------
443
444 /**
445 * Collects device summary results into a Bucket.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000446 * @throws RemoteException
447 */
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100448 Bucket getDeviceSummaryForNetwork() throws RemoteException {
449 mSummary = mSession.getDeviceSummaryForNetwork(mTemplate, mStartTimeStamp, mEndTimeStamp);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000450
451 // Setting enumeration index beyond end to avoid accidental enumeration over data that does
452 // not belong to the calling user.
453 mEnumerationIndex = mSummary.size();
454
455 return getSummaryAggregate();
456 }
457
458 /**
459 * Collects summary results and sets summary enumeration mode.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000460 * @throws RemoteException
461 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700462 void startSummaryEnumeration() throws RemoteException {
Antonio Cansado46c753672015-12-10 15:57:56 -0800463 mSummary = mSession.getSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp,
Antonio Cansado6965c182016-03-30 11:37:18 -0700464 false /* includeTags */);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000465 mEnumerationIndex = 0;
466 }
467
468 /**
469 * Collects history results for uid and resets history enumeration index.
470 */
471 void startHistoryEnumeration(int uid) {
Antonio Cansado46c753672015-12-10 15:57:56 -0800472 startHistoryEnumeration(uid, android.net.NetworkStats.TAG_NONE);
473 }
474
475 /**
476 * Collects history results for uid and resets history enumeration index.
477 */
478 void startHistoryEnumeration(int uid, int tag) {
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000479 mHistory = null;
480 try {
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100481 mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
Antonio Cansado46c753672015-12-10 15:57:56 -0800482 android.net.NetworkStats.SET_ALL, tag,
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100483 NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
Antonio Cansado3e883da2016-04-22 11:23:27 -0700484 setSingleUidTag(uid, tag);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000485 } catch (RemoteException e) {
486 Log.w(TAG, e);
487 // Leaving mHistory null
488 }
489 mEnumerationIndex = 0;
490 }
491
492 /**
493 * Starts uid enumeration for current user.
494 * @throws RemoteException
495 */
496 void startUserUidEnumeration() throws RemoteException {
Zoltan Szatmary-Ban887cffe2015-08-13 16:53:10 +0100497 // TODO: getRelevantUids should be sensitive to time interval. When that's done,
498 // the filtering logic below can be removed.
499 int[] uids = mSession.getRelevantUids();
500 // Filtering of uids with empty history.
501 IntArray filteredUids = new IntArray(uids.length);
502 for (int uid : uids) {
503 try {
504 NetworkStatsHistory history = mSession.getHistoryIntervalForUid(mTemplate, uid,
505 android.net.NetworkStats.SET_ALL, android.net.NetworkStats.TAG_NONE,
506 NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
507 if (history != null && history.size() > 0) {
508 filteredUids.add(uid);
509 }
510 } catch (RemoteException e) {
511 Log.w(TAG, "Error while getting history of uid " + uid, e);
512 }
513 }
514 mUids = filteredUids.toArray();
515 mUidOrUidIndex = -1;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000516 stepHistory();
517 }
518
519 /**
520 * Steps to next uid in enumeration and collects history for that.
521 */
522 private void stepHistory(){
523 if (hasNextUid()) {
524 stepUid();
525 mHistory = null;
526 try {
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100527 mHistory = mSession.getHistoryIntervalForUid(mTemplate, getUid(),
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100528 android.net.NetworkStats.SET_ALL, android.net.NetworkStats.TAG_NONE,
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100529 NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000530 } catch (RemoteException e) {
531 Log.w(TAG, e);
532 // Leaving mHistory null
533 }
534 mEnumerationIndex = 0;
535 }
536 }
537
538 private void fillBucketFromSummaryEntry(Bucket bucketOut) {
539 bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid);
Antonio Cansado46c753672015-12-10 15:57:56 -0800540 bucketOut.mTag = Bucket.convertTag(mRecycledSummaryEntry.tag);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000541 bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set);
Stephen Chenc926b732016-10-21 12:44:26 -0700542 bucketOut.mMetered = Bucket.convertMetered(mRecycledSummaryEntry.metered);
Jeff Davidsona6a78072016-01-11 16:02:17 -0800543 bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000544 bucketOut.mBeginTimeStamp = mStartTimeStamp;
545 bucketOut.mEndTimeStamp = mEndTimeStamp;
546 bucketOut.mRxBytes = mRecycledSummaryEntry.rxBytes;
547 bucketOut.mRxPackets = mRecycledSummaryEntry.rxPackets;
548 bucketOut.mTxBytes = mRecycledSummaryEntry.txBytes;
549 bucketOut.mTxPackets = mRecycledSummaryEntry.txPackets;
550 }
551
552 /**
553 * Getting the next item in summary enumeration.
554 * @param bucketOut Next item will be set here.
555 * @return true if a next item could be set.
556 */
557 private boolean getNextSummaryBucket(Bucket bucketOut) {
558 if (bucketOut != null && mEnumerationIndex < mSummary.size()) {
559 mRecycledSummaryEntry = mSummary.getValues(mEnumerationIndex++, mRecycledSummaryEntry);
560 fillBucketFromSummaryEntry(bucketOut);
561 return true;
562 }
563 return false;
564 }
565
566 Bucket getSummaryAggregate() {
567 if (mSummary == null) {
568 return null;
569 }
570 Bucket bucket = new Bucket();
571 if (mRecycledSummaryEntry == null) {
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100572 mRecycledSummaryEntry = new android.net.NetworkStats.Entry();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000573 }
574 mSummary.getTotal(mRecycledSummaryEntry);
575 fillBucketFromSummaryEntry(bucket);
576 return bucket;
577 }
578 /**
579 * Getting the next item in a history enumeration.
580 * @param bucketOut Next item will be set here.
581 * @return true if a next item could be set.
582 */
583 private boolean getNextHistoryBucket(Bucket bucketOut) {
584 if (bucketOut != null && mHistory != null) {
585 if (mEnumerationIndex < mHistory.size()) {
586 mRecycledHistoryEntry = mHistory.getValues(mEnumerationIndex++,
587 mRecycledHistoryEntry);
588 bucketOut.mUid = Bucket.convertUid(getUid());
Antonio Cansado3e883da2016-04-22 11:23:27 -0700589 bucketOut.mTag = Bucket.convertTag(mTag);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000590 bucketOut.mState = Bucket.STATE_ALL;
Stephen Chen1fee3a62016-10-18 16:41:47 -0700591 bucketOut.mMetered = Bucket.METERED_ALL;
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800592 bucketOut.mRoaming = Bucket.ROAMING_ALL;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000593 bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart;
594 bucketOut.mEndTimeStamp = mRecycledHistoryEntry.bucketStart +
595 mRecycledHistoryEntry.bucketDuration;
596 bucketOut.mRxBytes = mRecycledHistoryEntry.rxBytes;
597 bucketOut.mRxPackets = mRecycledHistoryEntry.rxPackets;
598 bucketOut.mTxBytes = mRecycledHistoryEntry.txBytes;
599 bucketOut.mTxPackets = mRecycledHistoryEntry.txPackets;
600 return true;
601 } else if (hasNextUid()) {
602 stepHistory();
603 return getNextHistoryBucket(bucketOut);
604 }
605 }
606 return false;
607 }
608
609 // ------------------ UID LOGIC------------------------
610
611 private boolean isUidEnumeration() {
612 return mUids != null;
613 }
614
615 private boolean hasNextUid() {
616 return isUidEnumeration() && (mUidOrUidIndex + 1) < mUids.length;
617 }
618
619 private int getUid() {
620 // Check if uid enumeration.
621 if (isUidEnumeration()) {
622 if (mUidOrUidIndex < 0 || mUidOrUidIndex >= mUids.length) {
623 throw new IndexOutOfBoundsException(
624 "Index=" + mUidOrUidIndex + " mUids.length=" + mUids.length);
625 }
626 return mUids[mUidOrUidIndex];
627 }
628 // Single uid mode.
629 return mUidOrUidIndex;
630 }
631
Antonio Cansado3e883da2016-04-22 11:23:27 -0700632 private void setSingleUidTag(int uid, int tag) {
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000633 mUidOrUidIndex = uid;
Antonio Cansado3e883da2016-04-22 11:23:27 -0700634 mTag = tag;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000635 }
636
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000637 private void stepUid() {
638 if (mUids != null) {
639 ++mUidOrUidIndex;
640 }
641 }
642}