163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey/* 263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Copyright (C) 2012 The Android Open Source Project 363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * 463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * you may not use this file except in compliance with the License. 663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * You may obtain a copy of the License at 763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * 863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * 1063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Unless required by applicable law or agreed to in writing, software 1163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 1263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * See the License for the specific language governing permissions and 1463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * limitations under the License. 1563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 1663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 1763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeypackage com.android.server.net; 1863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 1963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.net.NetworkStats.IFACE_ALL; 201f7e05eda687279ac9deb894f42ac927bd471ad2Jeff Davidsonimport static android.net.NetworkStats.ROAMING_NO; 211f7e05eda687279ac9deb894f42ac927bd471ad2Jeff Davidsonimport static android.net.NetworkStats.ROAMING_YES; 2263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.net.NetworkStats.SET_ALL; 2363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.net.NetworkStats.SET_DEFAULT; 2463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.net.NetworkStats.TAG_NONE; 2563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.net.NetworkStats.UID_ALL; 2663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.net.TrafficStats.UID_REMOVED; 2755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkeyimport static android.text.format.DateUtils.WEEK_IN_MILLIS; 2863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 2963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkIdentity; 3063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkStats; 3163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkStatsHistory; 3263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkTemplate; 3363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.TrafficStats; 349c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Banimport android.os.Binder; 3555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkeyimport android.util.ArrayMap; 3639606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile; 379c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Banimport android.util.IntArray; 3863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 39daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkeyimport com.android.internal.util.ArrayUtils; 4063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.FileRotator; 4163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 429c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban 4363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.google.android.collect.Lists; 4463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.google.android.collect.Maps; 4563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 461efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidsonimport libcore.io.IoUtils; 471efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson 4863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.BufferedInputStream; 4963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.DataInputStream; 5063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.DataOutputStream; 5163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.File; 5263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.FileNotFoundException; 5363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.IOException; 5463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.InputStream; 5555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkeyimport java.io.PrintWriter; 5663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.net.ProtocolException; 5763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.util.ArrayList; 5863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.util.Collections; 5963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.util.HashMap; 60e6585b32ea586743258a5457e2184ffc087f2d2fKenny Rootimport java.util.Objects; 6163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 6263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey/** 6363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Collection of {@link NetworkStatsHistory}, stored based on combined key of 6463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * {@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself. 6563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 6663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeypublic class NetworkStatsCollection implements FileRotator.Reader { 6763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** File header magic number: "ANET" */ 6863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int FILE_MAGIC = 0x414E4554; 6963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 7063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int VERSION_NETWORK_INIT = 1; 7163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 7263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int VERSION_UID_INIT = 1; 7363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int VERSION_UID_WITH_IDENT = 2; 7463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int VERSION_UID_WITH_TAG = 3; 7563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int VERSION_UID_WITH_SET = 4; 7663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 7763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int VERSION_UNIFIED_INIT = 16; 7863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 7955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey private ArrayMap<Key, NetworkStatsHistory> mStats = new ArrayMap<>(); 8063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 8170c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey private final long mBucketDuration; 8263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 8363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private long mStartMillis; 8463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private long mEndMillis; 8563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private long mTotalBytes; 8663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private boolean mDirty; 8763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 8863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStatsCollection(long bucketDuration) { 8963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mBucketDuration = bucketDuration; 9063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey reset(); 9163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 9263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 9363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void reset() { 9463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mStats.clear(); 9563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mStartMillis = Long.MAX_VALUE; 9663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mEndMillis = Long.MIN_VALUE; 9763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTotalBytes = 0; 9863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mDirty = false; 9963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 10063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 10163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public long getStartMillis() { 10263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return mStartMillis; 10363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 10463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 10570c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey /** 10670c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey * Return first atomic bucket in this collection, which is more conservative 10770c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey * than {@link #mStartMillis}. 10870c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey */ 10970c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey public long getFirstAtomicBucketMillis() { 11070c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey if (mStartMillis == Long.MAX_VALUE) { 11170c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey return Long.MAX_VALUE; 11270c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey } else { 11370c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey return mStartMillis + mBucketDuration; 11470c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey } 11570c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey } 11670c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey 11763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public long getEndMillis() { 11863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return mEndMillis; 11963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 12063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 12163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public long getTotalBytes() { 12263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return mTotalBytes; 12363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 12463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 12563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public boolean isDirty() { 12663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return mDirty; 12763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 12863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 12963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void clearDirty() { 13063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mDirty = false; 13163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 13263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 13363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public boolean isEmpty() { 13463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE; 13563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 13663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 1371efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) { 138cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado return getRelevantUids(accessLevel, Binder.getCallingUid()); 139cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 140cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 141cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel, 142cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado final int callerUid) { 1439c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban IntArray uids = new IntArray(); 1449c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban for (int i = 0; i < mStats.size(); i++) { 1459c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban final Key key = mStats.keyAt(i); 1461efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson if (NetworkStatsAccess.isAccessibleToUser(key.uid, callerUid, accessLevel)) { 1479c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban int j = uids.binarySearch(key.uid); 1489c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban 1499c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban if (j < 0) { 1509c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban j = ~j; 1519c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban uids.add(j, key.uid); 1529c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban } 1539c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban } 1549c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban } 1559c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban return uids.toArray(); 1569c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban } 1579c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban 15863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 15963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Combine all {@link NetworkStatsHistory} in this collection which match 16063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * the requested parameters. 16163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 16263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStatsHistory getHistory( 1631efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson NetworkTemplate template, int uid, int set, int tag, int fields, 1641efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson @NetworkStatsAccess.Level int accessLevel) { 1651efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson return getHistory(template, uid, set, tag, fields, Long.MIN_VALUE, Long.MAX_VALUE, 1661efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson accessLevel); 16770c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey } 16870c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey 16970c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey /** 17070c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey * Combine all {@link NetworkStatsHistory} in this collection which match 17170c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey * the requested parameters. 17270c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey */ 17370c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey public NetworkStatsHistory getHistory( 1741efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end, 1751efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson @NetworkStatsAccess.Level int accessLevel) { 176cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado return getHistory(template, uid, set, tag, fields, start, end, accessLevel, 177cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado Binder.getCallingUid()); 178cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 179cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 180cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado /** 181cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado * Combine all {@link NetworkStatsHistory} in this collection which match 182cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado * the requested parameters. 183cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado */ 184cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado public NetworkStatsHistory getHistory( 185cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end, 186cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado @NetworkStatsAccess.Level int accessLevel, int callerUid) { 1871efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson if (!NetworkStatsAccess.isAccessibleToUser(uid, callerUid, accessLevel)) { 1889c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban throw new SecurityException("Network stats history of uid " + uid 1899c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban + " is forbidden for caller " + callerUid); 1909c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban } 1919c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban 19263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory combined = new NetworkStatsHistory( 1939c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban mBucketDuration, start == end ? 1 : estimateBuckets(), fields); 1949c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban 1959c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban // shortcut when we know stats will be empty 1969c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban if (start == end) return combined; 1979c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban 19855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey for (int i = 0; i < mStats.size(); i++) { 19955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final Key key = mStats.keyAt(i); 20098170b0db191f916bf2a0f104f5d5057c2aaeaa9Wenchao Tong if (key.uid == uid && NetworkStats.setMatches(set, key.set) && key.tag == tag 20163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey && templateMatches(template, key.ident)) { 20255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final NetworkStatsHistory value = mStats.valueAt(i); 20355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey combined.recordHistory(value, start, end); 20463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 20563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 20663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return combined; 20763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 20863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 20963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 21063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Summarize all {@link NetworkStatsHistory} in this collection which match 21163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * the requested parameters. 21263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 2131efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson public NetworkStats getSummary(NetworkTemplate template, long start, long end, 2141efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson @NetworkStatsAccess.Level int accessLevel) { 215cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado return getSummary(template, start, end, accessLevel, Binder.getCallingUid()); 216cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 217cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 218cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado /** 219cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado * Summarize all {@link NetworkStatsHistory} in this collection which match 220cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado * the requested parameters. 221cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado */ 222cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado public NetworkStats getSummary(NetworkTemplate template, long start, long end, 223cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado @NetworkStatsAccess.Level int accessLevel, int callerUid) { 22463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long now = System.currentTimeMillis(); 22563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 22663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStats stats = new NetworkStats(end - start, 24); 22770c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey // shortcut when we know stats will be empty 22870c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey if (start == end) return stats; 22970c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey 2309c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban final NetworkStats.Entry entry = new NetworkStats.Entry(); 2319c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban NetworkStatsHistory.Entry historyEntry = null; 2329c5dfa5c79fff17f96bf977b86c0c9ceb8c3cf9bZoltan Szatmary-Ban 23355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey for (int i = 0; i < mStats.size(); i++) { 23455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final Key key = mStats.keyAt(i); 2351efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson if (templateMatches(template, key.ident) 2361efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson && NetworkStatsAccess.isAccessibleToUser(key.uid, callerUid, accessLevel) 23798170b0db191f916bf2a0f104f5d5057c2aaeaa9Wenchao Tong && key.set < NetworkStats.SET_DEBUG_START) { 23855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final NetworkStatsHistory value = mStats.valueAt(i); 23955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey historyEntry = value.getValues(start, end, now, historyEntry); 24063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 24163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.iface = IFACE_ALL; 24263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.uid = key.uid; 24363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.set = key.set; 24463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.tag = key.tag; 2451f7e05eda687279ac9deb894f42ac927bd471ad2Jeff Davidson entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO; 24663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.rxBytes = historyEntry.rxBytes; 24763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.rxPackets = historyEntry.rxPackets; 24863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.txBytes = historyEntry.txBytes; 24963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.txPackets = historyEntry.txPackets; 25063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.operations = historyEntry.operations; 25163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 25263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (!entry.isEmpty()) { 25363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey stats.combineValues(entry); 25463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 25563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 25663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 25763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 25863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return stats; 25963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 26063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 26163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 262bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey * Record given {@link android.net.NetworkStats.Entry} into this collection. 26363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 26463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void recordData(NetworkIdentitySet ident, int uid, int set, int tag, long start, 26563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey long end, NetworkStats.Entry entry) { 26670c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey final NetworkStatsHistory history = findOrCreateHistory(ident, uid, set, tag); 26770c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey history.recordData(start, end, entry); 26870c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey noteRecordedHistory(history.getStart(), history.getEnd(), entry.rxBytes + entry.txBytes); 26963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 27063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 27163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 27263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Record given {@link NetworkStatsHistory} into this collection. 27363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 27463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private void recordHistory(Key key, NetworkStatsHistory history) { 27563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (history.size() == 0) return; 27663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey noteRecordedHistory(history.getStart(), history.getEnd(), history.getTotalBytes()); 27763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 278ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey NetworkStatsHistory target = mStats.get(key); 279ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey if (target == null) { 280ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey target = new NetworkStatsHistory(history.getBucketDuration()); 281ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey mStats.put(key, target); 28263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 283ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey target.recordEntireHistory(history); 28463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 28563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 28663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 28763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Record all {@link NetworkStatsHistory} contained in the given collection 28863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * into this collection. 28963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 29063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void recordCollection(NetworkStatsCollection another) { 29155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey for (int i = 0; i < another.mStats.size(); i++) { 29255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final Key key = another.mStats.keyAt(i); 29355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final NetworkStatsHistory value = another.mStats.valueAt(i); 29455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey recordHistory(key, value); 29563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 29663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 29763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 29863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private NetworkStatsHistory findOrCreateHistory( 29963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey NetworkIdentitySet ident, int uid, int set, int tag) { 30063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final Key key = new Key(ident, uid, set, tag); 30163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory existing = mStats.get(key); 30263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 30363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // update when no existing, or when bucket duration changed 30463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey NetworkStatsHistory updated = null; 30563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (existing == null) { 30663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey updated = new NetworkStatsHistory(mBucketDuration, 10); 30763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } else if (existing.getBucketDuration() != mBucketDuration) { 30863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey updated = new NetworkStatsHistory(existing, mBucketDuration); 30963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 31063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 31163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (updated != null) { 31263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mStats.put(key, updated); 31363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return updated; 31463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } else { 31563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return existing; 31663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 31763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 31863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 319bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 32063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void read(InputStream in) throws IOException { 32163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey read(new DataInputStream(in)); 32263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 32363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 32463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void read(DataInputStream in) throws IOException { 32563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // verify file magic header intact 32663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int magic = in.readInt(); 32763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (magic != FILE_MAGIC) { 32863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey throw new ProtocolException("unexpected magic: " + magic); 32963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 33063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 33163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int version = in.readInt(); 33263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey switch (version) { 33363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey case VERSION_UNIFIED_INIT: { 33463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory)) 33563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int identSize = in.readInt(); 33663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (int i = 0; i < identSize; i++) { 33763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkIdentitySet ident = new NetworkIdentitySet(in); 33863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 33963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int size = in.readInt(); 34063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (int j = 0; j < size; j++) { 34163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int uid = in.readInt(); 34263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int set = in.readInt(); 34363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int tag = in.readInt(); 34463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 34563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final Key key = new Key(ident, uid, set, tag); 34663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory history = new NetworkStatsHistory(in); 34763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey recordHistory(key, history); 34863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 34963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 35063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey break; 35163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 35263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey default: { 35363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey throw new ProtocolException("unexpected version: " + version); 35463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 35563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 35663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 35763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 35863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void write(DataOutputStream out) throws IOException { 35963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // cluster key lists grouped by ident 36063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final HashMap<NetworkIdentitySet, ArrayList<Key>> keysByIdent = Maps.newHashMap(); 36163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (Key key : mStats.keySet()) { 36263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey ArrayList<Key> keys = keysByIdent.get(key.ident); 36363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (keys == null) { 36463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey keys = Lists.newArrayList(); 36563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey keysByIdent.put(key.ident, keys); 36663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 36763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey keys.add(key); 36863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 36963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 37063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(FILE_MAGIC); 37163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(VERSION_UNIFIED_INIT); 37263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 37363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(keysByIdent.size()); 37463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (NetworkIdentitySet ident : keysByIdent.keySet()) { 37563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final ArrayList<Key> keys = keysByIdent.get(ident); 37663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey ident.writeToStream(out); 37763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 37863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(keys.size()); 37963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (Key key : keys) { 38063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory history = mStats.get(key); 38163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(key.uid); 38263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(key.set); 38363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(key.tag); 38463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey history.writeToStream(out); 38563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 38663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 38763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 38863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.flush(); 38963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 39063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 39163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey @Deprecated 39263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void readLegacyNetwork(File file) throws IOException { 39363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final AtomicFile inputFile = new AtomicFile(file); 39463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 39563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey DataInputStream in = null; 39663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey try { 39763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey in = new DataInputStream(new BufferedInputStream(inputFile.openRead())); 39863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 39963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // verify file magic header intact 40063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int magic = in.readInt(); 40163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (magic != FILE_MAGIC) { 40263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey throw new ProtocolException("unexpected magic: " + magic); 40363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 40463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 40563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int version = in.readInt(); 40663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey switch (version) { 40763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey case VERSION_NETWORK_INIT: { 40863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // network := size *(NetworkIdentitySet NetworkStatsHistory) 40963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int size = in.readInt(); 41063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (int i = 0; i < size; i++) { 41163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkIdentitySet ident = new NetworkIdentitySet(in); 41263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory history = new NetworkStatsHistory(in); 41363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 41463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final Key key = new Key(ident, UID_ALL, SET_ALL, TAG_NONE); 41563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey recordHistory(key, history); 41663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 41763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey break; 41863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 41963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey default: { 42063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey throw new ProtocolException("unexpected version: " + version); 42163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 42263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 42363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } catch (FileNotFoundException e) { 42463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // missing stats is okay, probably first boot 42563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } finally { 42663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey IoUtils.closeQuietly(in); 42763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 42863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 42963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 43063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey @Deprecated 43163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void readLegacyUid(File file, boolean onlyTags) throws IOException { 43263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final AtomicFile inputFile = new AtomicFile(file); 43363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 43463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey DataInputStream in = null; 43563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey try { 43663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey in = new DataInputStream(new BufferedInputStream(inputFile.openRead())); 43763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 43863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // verify file magic header intact 43963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int magic = in.readInt(); 44063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (magic != FILE_MAGIC) { 44163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey throw new ProtocolException("unexpected magic: " + magic); 44263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 44363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 44463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int version = in.readInt(); 44563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey switch (version) { 44663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey case VERSION_UID_INIT: { 44763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // uid := size *(UID NetworkStatsHistory) 44863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 44963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // drop this data version, since we don't have a good 45063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // mapping into NetworkIdentitySet. 45163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey break; 45263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 45363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey case VERSION_UID_WITH_IDENT: { 45463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory)) 45563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 45663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // drop this data version, since this version only existed 45763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // for a short time. 45863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey break; 45963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 46063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey case VERSION_UID_WITH_TAG: 46163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey case VERSION_UID_WITH_SET: { 46263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory)) 46363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int identSize = in.readInt(); 46463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (int i = 0; i < identSize; i++) { 46563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkIdentitySet ident = new NetworkIdentitySet(in); 46663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 46763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int size = in.readInt(); 46863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (int j = 0; j < size; j++) { 46963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int uid = in.readInt(); 47063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int set = (version >= VERSION_UID_WITH_SET) ? in.readInt() 47163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey : SET_DEFAULT; 47263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int tag = in.readInt(); 47363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 47463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final Key key = new Key(ident, uid, set, tag); 47563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory history = new NetworkStatsHistory(in); 47663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 47763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if ((tag == TAG_NONE) != onlyTags) { 47863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey recordHistory(key, history); 47963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 48063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 48163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 48263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey break; 48363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 48463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey default: { 48563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey throw new ProtocolException("unexpected version: " + version); 48663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 48763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 48863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } catch (FileNotFoundException e) { 48963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // missing stats is okay, probably first boot 49063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } finally { 49163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey IoUtils.closeQuietly(in); 49263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 49363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 49463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 49563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 49663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Remove any {@link NetworkStatsHistory} attributed to the requested UID, 49763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * moving any {@link NetworkStats#TAG_NONE} series to 49863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * {@link TrafficStats#UID_REMOVED}. 49963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 500daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey public void removeUids(int[] uids) { 50163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final ArrayList<Key> knownKeys = Lists.newArrayList(); 50263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey knownKeys.addAll(mStats.keySet()); 50363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 50463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // migrate all UID stats into special "removed" bucket 50563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (Key key : knownKeys) { 506daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey if (ArrayUtils.contains(uids, key.uid)) { 50763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // only migrate combined TAG_NONE history 50863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (key.tag == TAG_NONE) { 50963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory uidHistory = mStats.get(key); 51063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory removedHistory = findOrCreateHistory( 51163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey key.ident, UID_REMOVED, SET_DEFAULT, TAG_NONE); 51263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey removedHistory.recordEntireHistory(uidHistory); 51363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 51463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mStats.remove(key); 51563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mDirty = true; 51663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 51763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 51863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 51963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 52063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private void noteRecordedHistory(long startMillis, long endMillis, long totalBytes) { 52163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (startMillis < mStartMillis) mStartMillis = startMillis; 52263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (endMillis > mEndMillis) mEndMillis = endMillis; 52363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTotalBytes += totalBytes; 52463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mDirty = true; 52563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 52663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 52763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private int estimateBuckets() { 52855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey return (int) (Math.min(mEndMillis - mStartMillis, WEEK_IN_MILLIS * 5) 52963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey / mBucketDuration); 53063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 53163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 53263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void dump(IndentingPrintWriter pw) { 53363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final ArrayList<Key> keys = Lists.newArrayList(); 53463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey keys.addAll(mStats.keySet()); 53563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey Collections.sort(keys); 53663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 53763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (Key key : keys) { 53863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.print("ident="); pw.print(key.ident.toString()); 53963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.print(" uid="); pw.print(key.uid); 54063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.print(" set="); pw.print(NetworkStats.setToString(key.set)); 54163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.print(" tag="); pw.println(NetworkStats.tagToString(key.tag)); 54263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 54363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory history = mStats.get(key); 54463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.increaseIndent(); 54563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey history.dump(pw, true); 54663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.decreaseIndent(); 54763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 54863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 54963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 55055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey public void dumpCheckin(PrintWriter pw, long start, long end) { 55155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateMobileWildcard(), "cell"); 55255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateWifiWildcard(), "wifi"); 55355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateEthernet(), "eth"); 55455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateBluetooth(), "bt"); 55555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 55655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 55755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey /** 55855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey * Dump all contained stats that match requested parameters, but group 55955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey * together all matching {@link NetworkTemplate} under a single prefix. 56055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey */ 56155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey private void dumpCheckin(PrintWriter pw, long start, long end, NetworkTemplate groupTemplate, 56255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey String groupPrefix) { 56355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final ArrayMap<Key, NetworkStatsHistory> grouped = new ArrayMap<>(); 56455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 56555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey // Walk through all history, grouping by matching network templates 56655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey for (int i = 0; i < mStats.size(); i++) { 56755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final Key key = mStats.keyAt(i); 56855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final NetworkStatsHistory value = mStats.valueAt(i); 56955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 57055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (!templateMatches(groupTemplate, key.ident)) continue; 57198170b0db191f916bf2a0f104f5d5057c2aaeaa9Wenchao Tong if (key.set >= NetworkStats.SET_DEBUG_START) continue; 57255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 57355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final Key groupKey = new Key(null, key.uid, key.set, key.tag); 57455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey NetworkStatsHistory groupHistory = grouped.get(groupKey); 57555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (groupHistory == null) { 57655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey groupHistory = new NetworkStatsHistory(value.getBucketDuration()); 57755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey grouped.put(groupKey, groupHistory); 57855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 57955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey groupHistory.recordHistory(value, start, end); 58055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 58155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 58255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey for (int i = 0; i < grouped.size(); i++) { 58355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final Key key = grouped.keyAt(i); 58455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final NetworkStatsHistory value = grouped.valueAt(i); 58555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 58655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (value.size() == 0) continue; 58755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 58855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.print("c,"); 58955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.print(groupPrefix); pw.print(','); 59055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.print(key.uid); pw.print(','); 59155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.print(NetworkStats.setToCheckinString(key.set)); pw.print(','); 59255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.print(key.tag); 59355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.println(); 59455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 59555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey value.dumpCheckin(pw); 59655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 59755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 59855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 59963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 60063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity} 60163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * in the given {@link NetworkIdentitySet}. 60263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 60363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static boolean templateMatches(NetworkTemplate template, NetworkIdentitySet identSet) { 60463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (NetworkIdentity ident : identSet) { 60563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (template.matches(ident)) { 60663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return true; 60763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 60863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 60963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return false; 61063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 61163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 61263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static class Key implements Comparable<Key> { 61363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public final NetworkIdentitySet ident; 61463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public final int uid; 61563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public final int set; 61663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public final int tag; 61763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 61863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final int hashCode; 61963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 62063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public Key(NetworkIdentitySet ident, int uid, int set, int tag) { 62163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey this.ident = ident; 62263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey this.uid = uid; 62363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey this.set = set; 62463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey this.tag = tag; 625e6585b32ea586743258a5457e2184ffc087f2d2fKenny Root hashCode = Objects.hash(ident, uid, set, tag); 62663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 62763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 62863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey @Override 62963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public int hashCode() { 63063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return hashCode; 63163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 63263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 63363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey @Override 63463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public boolean equals(Object obj) { 63563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (obj instanceof Key) { 63663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final Key key = (Key) obj; 63763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return uid == key.uid && set == key.set && tag == key.tag 638e6585b32ea586743258a5457e2184ffc087f2d2fKenny Root && Objects.equals(ident, key.ident); 63963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 64063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return false; 64163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 64263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 643bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 64463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public int compareTo(Key another) { 64555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey int res = 0; 64655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (ident != null && another.ident != null) { 64755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey res = ident.compareTo(another.ident); 64855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 64955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (res == 0) { 65055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey res = Integer.compare(uid, another.uid); 65155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 65255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (res == 0) { 65355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey res = Integer.compare(set, another.set); 65455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 65555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (res == 0) { 65655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey res = Integer.compare(tag, another.tag); 65755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 65855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey return res; 65963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 66063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 66163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey} 662