blob: 226aa8f2706da4a6f5514f7ab542b26c421a5ba6 [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 */
167 @IntDef({ROAMING_ALL, ROAMING_NO, ROAMING_YES})
168 @Retention(RetentionPolicy.SOURCE)
169 public @interface Roaming {}
170
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800171 /**
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800172 * Combined usage across all roaming states. Covers both roaming and non-roaming usage.
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800173 */
174 public static final int ROAMING_ALL = -1;
175
176 /**
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800177 * Usage that occurs on a home, non-roaming network.
178 *
179 * <p>Any cellular usage in this bucket was incurred while the device was connected to a
180 * tower owned or operated by the user's wireless carrier, or a tower that the user's
181 * wireless carrier has indicated should be treated as a home network regardless.
182 *
183 * <p>This is also the default value for network types that do not support roaming.
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800184 */
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800185 public static final int ROAMING_NO = 0x1;
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800186
187 /**
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800188 * Usage that occurs on a roaming network.
189 *
190 * <p>Any cellular usage in this bucket as incurred while the device was roaming on another
191 * carrier's network, for which additional charges may apply.
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800192 */
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800193 public static final int ROAMING_YES = 0x2;
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800194
Antonio Cansado46c753672015-12-10 15:57:56 -0800195 /**
Antonio Cansado46c753672015-12-10 15:57:56 -0800196 * Special TAG value for total data across all tags
197 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700198 public static final int TAG_NONE = android.net.NetworkStats.TAG_NONE;
Antonio Cansado46c753672015-12-10 15:57:56 -0800199
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000200 private int mUid;
Antonio Cansado46c753672015-12-10 15:57:56 -0800201 private int mTag;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000202 private int mState;
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800203 private int mRoaming;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000204 private long mBeginTimeStamp;
205 private long mEndTimeStamp;
206 private long mRxBytes;
207 private long mRxPackets;
208 private long mTxBytes;
209 private long mTxPackets;
210
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800211 private static @State int convertState(int networkStatsSet) {
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000212 switch (networkStatsSet) {
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100213 case android.net.NetworkStats.SET_ALL : return STATE_ALL;
214 case android.net.NetworkStats.SET_DEFAULT : return STATE_DEFAULT;
215 case android.net.NetworkStats.SET_FOREGROUND : return STATE_FOREGROUND;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000216 }
217 return 0;
218 }
219
220 private static int convertUid(int uid) {
221 switch (uid) {
222 case TrafficStats.UID_REMOVED: return UID_REMOVED;
223 case TrafficStats.UID_TETHERING: return UID_TETHERING;
224 }
225 return uid;
226 }
227
Antonio Cansado46c753672015-12-10 15:57:56 -0800228 private static int convertTag(int tag) {
229 switch (tag) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700230 case android.net.NetworkStats.TAG_NONE: return TAG_NONE;
Antonio Cansado46c753672015-12-10 15:57:56 -0800231 }
232 return tag;
233 }
234
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800235 private static @Roaming int convertRoaming(int roaming) {
Jeff Davidsona6a78072016-01-11 16:02:17 -0800236 switch (roaming) {
237 case android.net.NetworkStats.ROAMING_ALL : return ROAMING_ALL;
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800238 case android.net.NetworkStats.ROAMING_NO: return ROAMING_NO;
239 case android.net.NetworkStats.ROAMING_YES: return ROAMING_YES;
Jeff Davidsona6a78072016-01-11 16:02:17 -0800240 }
241 return 0;
242 }
243
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000244 public Bucket() {
245 }
246
247 /**
248 * Key of the bucket. Usually an app uid or one of the following special values:<p />
249 * <ul>
250 * <li>{@link #UID_REMOVED}</li>
251 * <li>{@link #UID_TETHERING}</li>
252 * <li>{@link android.os.Process#SYSTEM_UID}</li>
253 * </ul>
254 * @return Bucket key.
255 */
256 public int getUid() {
257 return mUid;
258 }
259
260 /**
Antonio Cansado46c753672015-12-10 15:57:56 -0800261 * Tag of the bucket.<p />
262 * @return Bucket tag.
263 */
264 public int getTag() {
265 return mTag;
266 }
267
268 /**
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000269 * Usage state. One of the following values:<p/>
270 * <ul>
271 * <li>{@link #STATE_ALL}</li>
272 * <li>{@link #STATE_DEFAULT}</li>
273 * <li>{@link #STATE_FOREGROUND}</li>
274 * </ul>
275 * @return Usage state.
276 */
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800277 public @State int getState() {
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000278 return mState;
279 }
280
281 /**
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800282 * Roaming state. One of the following values:<p/>
283 * <ul>
284 * <li>{@link #ROAMING_ALL}</li>
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800285 * <li>{@link #ROAMING_NO}</li>
286 * <li>{@link #ROAMING_YES}</li>
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800287 * </ul>
288 */
Jeff Davidson1f7e05e2016-03-10 13:21:38 -0800289 public @Roaming int getRoaming() {
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800290 return mRoaming;
291 }
292
293 /**
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000294 * Start timestamp of the bucket's time interval. Defined in terms of "Unix time", see
295 * {@link java.lang.System#currentTimeMillis}.
296 * @return Start of interval.
297 */
298 public long getStartTimeStamp() {
299 return mBeginTimeStamp;
300 }
301
302 /**
303 * End timestamp of the bucket's time interval. Defined in terms of "Unix time", see
304 * {@link java.lang.System#currentTimeMillis}.
305 * @return End of interval.
306 */
307 public long getEndTimeStamp() {
308 return mEndTimeStamp;
309 }
310
311 /**
312 * Number of bytes received during the bucket's time interval. Statistics are measured at
313 * the network layer, so they include both TCP and UDP usage.
314 * @return Number of bytes.
315 */
316 public long getRxBytes() {
317 return mRxBytes;
318 }
319
320 /**
321 * Number of bytes transmitted during the bucket's time interval. Statistics are measured at
322 * the network layer, so they include both TCP and UDP usage.
323 * @return Number of bytes.
324 */
325 public long getTxBytes() {
326 return mTxBytes;
327 }
328
329 /**
330 * Number of packets received during the bucket's time interval. Statistics are measured at
331 * the network layer, so they include both TCP and UDP usage.
332 * @return Number of packets.
333 */
334 public long getRxPackets() {
335 return mRxPackets;
336 }
337
338 /**
339 * Number of packets transmitted during the bucket's time interval. Statistics are measured
340 * at the network layer, so they include both TCP and UDP usage.
341 * @return Number of packets.
342 */
343 public long getTxPackets() {
344 return mTxPackets;
345 }
346 }
347
348 /**
349 * Fills the recycled bucket with data of the next bin in the enumeration.
350 * @param bucketOut Bucket to be filled with data.
351 * @return true if successfully filled the bucket, false otherwise.
352 */
353 public boolean getNextBucket(Bucket bucketOut) {
354 if (mSummary != null) {
355 return getNextSummaryBucket(bucketOut);
356 } else {
357 return getNextHistoryBucket(bucketOut);
358 }
359 }
360
361 /**
362 * Check if it is possible to ask for a next bucket in the enumeration.
363 * @return true if there is at least one more bucket.
364 */
365 public boolean hasNextBucket() {
366 if (mSummary != null) {
367 return mEnumerationIndex < mSummary.size();
368 } else if (mHistory != null) {
369 return mEnumerationIndex < mHistory.size()
370 || hasNextUid();
371 }
372 return false;
373 }
374
375 /**
376 * Closes the enumeration. Call this method before this object gets out of scope.
377 */
378 @Override
379 public void close() {
380 if (mSession != null) {
381 try {
382 mSession.close();
383 } catch (RemoteException e) {
384 Log.w(TAG, e);
385 // Otherwise, meh
386 }
387 }
388 mSession = null;
389 if (mCloseGuard != null) {
390 mCloseGuard.close();
391 }
392 }
393
394 // -------------------------END OF PUBLIC API-----------------------------------
395
396 /**
397 * Collects device summary results into a Bucket.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000398 * @throws RemoteException
399 */
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100400 Bucket getDeviceSummaryForNetwork() throws RemoteException {
401 mSummary = mSession.getDeviceSummaryForNetwork(mTemplate, mStartTimeStamp, mEndTimeStamp);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000402
403 // Setting enumeration index beyond end to avoid accidental enumeration over data that does
404 // not belong to the calling user.
405 mEnumerationIndex = mSummary.size();
406
407 return getSummaryAggregate();
408 }
409
410 /**
411 * Collects summary results and sets summary enumeration mode.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000412 * @throws RemoteException
413 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700414 void startSummaryEnumeration() throws RemoteException {
Antonio Cansado46c753672015-12-10 15:57:56 -0800415 mSummary = mSession.getSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp,
Antonio Cansado6965c182016-03-30 11:37:18 -0700416 false /* includeTags */);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000417 mEnumerationIndex = 0;
418 }
419
420 /**
421 * Collects history results for uid and resets history enumeration index.
422 */
423 void startHistoryEnumeration(int uid) {
Antonio Cansado46c753672015-12-10 15:57:56 -0800424 startHistoryEnumeration(uid, android.net.NetworkStats.TAG_NONE);
425 }
426
427 /**
428 * Collects history results for uid and resets history enumeration index.
429 */
430 void startHistoryEnumeration(int uid, int tag) {
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000431 mHistory = null;
432 try {
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100433 mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
Antonio Cansado46c753672015-12-10 15:57:56 -0800434 android.net.NetworkStats.SET_ALL, tag,
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100435 NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
Antonio Cansado3e883da2016-04-22 11:23:27 -0700436 setSingleUidTag(uid, tag);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000437 } catch (RemoteException e) {
438 Log.w(TAG, e);
439 // Leaving mHistory null
440 }
441 mEnumerationIndex = 0;
442 }
443
444 /**
445 * Starts uid enumeration for current user.
446 * @throws RemoteException
447 */
448 void startUserUidEnumeration() throws RemoteException {
Zoltan Szatmary-Ban887cffe2015-08-13 16:53:10 +0100449 // TODO: getRelevantUids should be sensitive to time interval. When that's done,
450 // the filtering logic below can be removed.
451 int[] uids = mSession.getRelevantUids();
452 // Filtering of uids with empty history.
453 IntArray filteredUids = new IntArray(uids.length);
454 for (int uid : uids) {
455 try {
456 NetworkStatsHistory history = mSession.getHistoryIntervalForUid(mTemplate, uid,
457 android.net.NetworkStats.SET_ALL, android.net.NetworkStats.TAG_NONE,
458 NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
459 if (history != null && history.size() > 0) {
460 filteredUids.add(uid);
461 }
462 } catch (RemoteException e) {
463 Log.w(TAG, "Error while getting history of uid " + uid, e);
464 }
465 }
466 mUids = filteredUids.toArray();
467 mUidOrUidIndex = -1;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000468 stepHistory();
469 }
470
471 /**
472 * Steps to next uid in enumeration and collects history for that.
473 */
474 private void stepHistory(){
475 if (hasNextUid()) {
476 stepUid();
477 mHistory = null;
478 try {
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100479 mHistory = mSession.getHistoryIntervalForUid(mTemplate, getUid(),
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100480 android.net.NetworkStats.SET_ALL, android.net.NetworkStats.TAG_NONE,
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100481 NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000482 } catch (RemoteException e) {
483 Log.w(TAG, e);
484 // Leaving mHistory null
485 }
486 mEnumerationIndex = 0;
487 }
488 }
489
490 private void fillBucketFromSummaryEntry(Bucket bucketOut) {
491 bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid);
Antonio Cansado46c753672015-12-10 15:57:56 -0800492 bucketOut.mTag = Bucket.convertTag(mRecycledSummaryEntry.tag);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000493 bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set);
Jeff Davidsona6a78072016-01-11 16:02:17 -0800494 bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000495 bucketOut.mBeginTimeStamp = mStartTimeStamp;
496 bucketOut.mEndTimeStamp = mEndTimeStamp;
497 bucketOut.mRxBytes = mRecycledSummaryEntry.rxBytes;
498 bucketOut.mRxPackets = mRecycledSummaryEntry.rxPackets;
499 bucketOut.mTxBytes = mRecycledSummaryEntry.txBytes;
500 bucketOut.mTxPackets = mRecycledSummaryEntry.txPackets;
501 }
502
503 /**
504 * Getting the next item in summary enumeration.
505 * @param bucketOut Next item will be set here.
506 * @return true if a next item could be set.
507 */
508 private boolean getNextSummaryBucket(Bucket bucketOut) {
509 if (bucketOut != null && mEnumerationIndex < mSummary.size()) {
510 mRecycledSummaryEntry = mSummary.getValues(mEnumerationIndex++, mRecycledSummaryEntry);
511 fillBucketFromSummaryEntry(bucketOut);
512 return true;
513 }
514 return false;
515 }
516
517 Bucket getSummaryAggregate() {
518 if (mSummary == null) {
519 return null;
520 }
521 Bucket bucket = new Bucket();
522 if (mRecycledSummaryEntry == null) {
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100523 mRecycledSummaryEntry = new android.net.NetworkStats.Entry();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000524 }
525 mSummary.getTotal(mRecycledSummaryEntry);
526 fillBucketFromSummaryEntry(bucket);
527 return bucket;
528 }
529 /**
530 * Getting the next item in a history enumeration.
531 * @param bucketOut Next item will be set here.
532 * @return true if a next item could be set.
533 */
534 private boolean getNextHistoryBucket(Bucket bucketOut) {
535 if (bucketOut != null && mHistory != null) {
536 if (mEnumerationIndex < mHistory.size()) {
537 mRecycledHistoryEntry = mHistory.getValues(mEnumerationIndex++,
538 mRecycledHistoryEntry);
539 bucketOut.mUid = Bucket.convertUid(getUid());
Antonio Cansado3e883da2016-04-22 11:23:27 -0700540 bucketOut.mTag = Bucket.convertTag(mTag);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000541 bucketOut.mState = Bucket.STATE_ALL;
Jeff Davidson05ae0fe2016-01-06 13:53:36 -0800542 bucketOut.mRoaming = Bucket.ROAMING_ALL;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000543 bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart;
544 bucketOut.mEndTimeStamp = mRecycledHistoryEntry.bucketStart +
545 mRecycledHistoryEntry.bucketDuration;
546 bucketOut.mRxBytes = mRecycledHistoryEntry.rxBytes;
547 bucketOut.mRxPackets = mRecycledHistoryEntry.rxPackets;
548 bucketOut.mTxBytes = mRecycledHistoryEntry.txBytes;
549 bucketOut.mTxPackets = mRecycledHistoryEntry.txPackets;
550 return true;
551 } else if (hasNextUid()) {
552 stepHistory();
553 return getNextHistoryBucket(bucketOut);
554 }
555 }
556 return false;
557 }
558
559 // ------------------ UID LOGIC------------------------
560
561 private boolean isUidEnumeration() {
562 return mUids != null;
563 }
564
565 private boolean hasNextUid() {
566 return isUidEnumeration() && (mUidOrUidIndex + 1) < mUids.length;
567 }
568
569 private int getUid() {
570 // Check if uid enumeration.
571 if (isUidEnumeration()) {
572 if (mUidOrUidIndex < 0 || mUidOrUidIndex >= mUids.length) {
573 throw new IndexOutOfBoundsException(
574 "Index=" + mUidOrUidIndex + " mUids.length=" + mUids.length);
575 }
576 return mUids[mUidOrUidIndex];
577 }
578 // Single uid mode.
579 return mUidOrUidIndex;
580 }
581
Antonio Cansado3e883da2016-04-22 11:23:27 -0700582 private void setSingleUidTag(int uid, int tag) {
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000583 mUidOrUidIndex = uid;
Antonio Cansado3e883da2016-04-22 11:23:27 -0700584 mTag = tag;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000585 }
586
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000587 private void stepUid() {
588 if (mUids != null) {
589 ++mUidOrUidIndex;
590 }
591 }
592}