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; 2063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.net.NetworkStats.SET_ALL; 2163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.net.NetworkStats.SET_DEFAULT; 2263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.net.NetworkStats.TAG_NONE; 2363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.net.NetworkStats.UID_ALL; 2463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.net.TrafficStats.UID_REMOVED; 2563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 2663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkIdentity; 2763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkStats; 2863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkStatsHistory; 2963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkTemplate; 3063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.TrafficStats; 3163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.text.format.DateUtils; 3239606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile; 3363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 34daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkeyimport com.android.internal.util.ArrayUtils; 3563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.FileRotator; 3663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 3763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.Objects; 3863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.google.android.collect.Lists; 3963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.google.android.collect.Maps; 4063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 4163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.BufferedInputStream; 4263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.DataInputStream; 4363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.DataOutputStream; 4463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.File; 4563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.FileNotFoundException; 4663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.IOException; 4763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.InputStream; 4863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.net.ProtocolException; 4963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.util.ArrayList; 5063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.util.Collections; 5163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.util.HashMap; 5263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.util.Map; 5363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 5463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport libcore.io.IoUtils; 5563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 5663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey/** 5763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Collection of {@link NetworkStatsHistory}, stored based on combined key of 5863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * {@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself. 5963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 6063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeypublic class NetworkStatsCollection implements FileRotator.Reader { 6163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** File header magic number: "ANET" */ 6263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int FILE_MAGIC = 0x414E4554; 6363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 6463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int VERSION_NETWORK_INIT = 1; 6563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 6663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int VERSION_UID_INIT = 1; 6763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int VERSION_UID_WITH_IDENT = 2; 6863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int VERSION_UID_WITH_TAG = 3; 6963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int VERSION_UID_WITH_SET = 4; 7063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 7163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final int VERSION_UNIFIED_INIT = 16; 7263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 7363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private HashMap<Key, NetworkStatsHistory> mStats = Maps.newHashMap(); 7463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 7570c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey private final long mBucketDuration; 7663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 7763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private long mStartMillis; 7863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private long mEndMillis; 7963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private long mTotalBytes; 8063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private boolean mDirty; 8163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 8263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStatsCollection(long bucketDuration) { 8363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mBucketDuration = bucketDuration; 8463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey reset(); 8563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 8663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 8763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void reset() { 8863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mStats.clear(); 8963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mStartMillis = Long.MAX_VALUE; 9063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mEndMillis = Long.MIN_VALUE; 9163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTotalBytes = 0; 9263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mDirty = false; 9363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 9463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 9563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public long getStartMillis() { 9663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return mStartMillis; 9763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 9863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 9970c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey /** 10070c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey * Return first atomic bucket in this collection, which is more conservative 10170c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey * than {@link #mStartMillis}. 10270c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey */ 10370c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey public long getFirstAtomicBucketMillis() { 10470c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey if (mStartMillis == Long.MAX_VALUE) { 10570c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey return Long.MAX_VALUE; 10670c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey } else { 10770c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey return mStartMillis + mBucketDuration; 10870c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey } 10970c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey } 11070c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey 11163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public long getEndMillis() { 11263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return mEndMillis; 11363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 11463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 11563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public long getTotalBytes() { 11663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return mTotalBytes; 11763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 11863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 11963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public boolean isDirty() { 12063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return mDirty; 12163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 12263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 12363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void clearDirty() { 12463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mDirty = false; 12563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 12663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 12763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public boolean isEmpty() { 12863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE; 12963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 13063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 13163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 13263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Combine all {@link NetworkStatsHistory} in this collection which match 13363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * the requested parameters. 13463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 13563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStatsHistory getHistory( 13663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey NetworkTemplate template, int uid, int set, int tag, int fields) { 13770c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey return getHistory(template, uid, set, tag, fields, Long.MIN_VALUE, Long.MAX_VALUE); 13870c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey } 13970c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey 14070c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey /** 14170c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey * Combine all {@link NetworkStatsHistory} in this collection which match 14270c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey * the requested parameters. 14370c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey */ 14470c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey public NetworkStatsHistory getHistory( 14570c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end) { 14663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory combined = new NetworkStatsHistory( 14763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mBucketDuration, estimateBuckets(), fields); 14863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (Map.Entry<Key, NetworkStatsHistory> entry : mStats.entrySet()) { 14963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final Key key = entry.getKey(); 15063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final boolean setMatches = set == SET_ALL || key.set == set; 15163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (key.uid == uid && setMatches && key.tag == tag 15263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey && templateMatches(template, key.ident)) { 15370c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey combined.recordHistory(entry.getValue(), start, end); 15463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 15563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 15663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return combined; 15763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 15863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 15963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 16063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Summarize all {@link NetworkStatsHistory} in this collection which match 16163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * the requested parameters. 16263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 16363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStats getSummary(NetworkTemplate template, long start, long end) { 16463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long now = System.currentTimeMillis(); 16563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 16663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStats stats = new NetworkStats(end - start, 24); 16763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStats.Entry entry = new NetworkStats.Entry(); 16863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey NetworkStatsHistory.Entry historyEntry = null; 16963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 17070c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey // shortcut when we know stats will be empty 17170c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey if (start == end) return stats; 17270c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey 17363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (Map.Entry<Key, NetworkStatsHistory> mapEntry : mStats.entrySet()) { 17463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final Key key = mapEntry.getKey(); 17563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (templateMatches(template, key.ident)) { 17663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory history = mapEntry.getValue(); 17763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey historyEntry = history.getValues(start, end, now, historyEntry); 17863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 17963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.iface = IFACE_ALL; 18063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.uid = key.uid; 18163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.set = key.set; 18263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.tag = key.tag; 18363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.rxBytes = historyEntry.rxBytes; 18463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.rxPackets = historyEntry.rxPackets; 18563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.txBytes = historyEntry.txBytes; 18663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.txPackets = historyEntry.txPackets; 18763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry.operations = historyEntry.operations; 18863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 18963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (!entry.isEmpty()) { 19063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey stats.combineValues(entry); 19163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 19263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 19363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 19463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 19563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return stats; 19663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 19763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 19863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 199bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey * Record given {@link android.net.NetworkStats.Entry} into this collection. 20063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 20163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void recordData(NetworkIdentitySet ident, int uid, int set, int tag, long start, 20263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey long end, NetworkStats.Entry entry) { 20370c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey final NetworkStatsHistory history = findOrCreateHistory(ident, uid, set, tag); 20470c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey history.recordData(start, end, entry); 20570c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey noteRecordedHistory(history.getStart(), history.getEnd(), entry.rxBytes + entry.txBytes); 20663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 20763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 20863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 20963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Record given {@link NetworkStatsHistory} into this collection. 21063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 21163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private void recordHistory(Key key, NetworkStatsHistory history) { 21263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (history.size() == 0) return; 21363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey noteRecordedHistory(history.getStart(), history.getEnd(), history.getTotalBytes()); 21463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 215ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey NetworkStatsHistory target = mStats.get(key); 216ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey if (target == null) { 217ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey target = new NetworkStatsHistory(history.getBucketDuration()); 218ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey mStats.put(key, target); 21963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 220ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey target.recordEntireHistory(history); 22163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 22263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 22363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 22463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Record all {@link NetworkStatsHistory} contained in the given collection 22563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * into this collection. 22663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 22763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void recordCollection(NetworkStatsCollection another) { 22863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (Map.Entry<Key, NetworkStatsHistory> entry : another.mStats.entrySet()) { 22963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey recordHistory(entry.getKey(), entry.getValue()); 23063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 23163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 23263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 23363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private NetworkStatsHistory findOrCreateHistory( 23463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey NetworkIdentitySet ident, int uid, int set, int tag) { 23563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final Key key = new Key(ident, uid, set, tag); 23663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory existing = mStats.get(key); 23763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 23863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // update when no existing, or when bucket duration changed 23963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey NetworkStatsHistory updated = null; 24063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (existing == null) { 24163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey updated = new NetworkStatsHistory(mBucketDuration, 10); 24263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } else if (existing.getBucketDuration() != mBucketDuration) { 24363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey updated = new NetworkStatsHistory(existing, mBucketDuration); 24463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 24563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 24663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (updated != null) { 24763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mStats.put(key, updated); 24863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return updated; 24963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } else { 25063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return existing; 25163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 25263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 25363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 254bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 25563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void read(InputStream in) throws IOException { 25663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey read(new DataInputStream(in)); 25763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 25863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 25963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void read(DataInputStream in) throws IOException { 26063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // verify file magic header intact 26163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int magic = in.readInt(); 26263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (magic != FILE_MAGIC) { 26363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey throw new ProtocolException("unexpected magic: " + magic); 26463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 26563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 26663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int version = in.readInt(); 26763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey switch (version) { 26863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey case VERSION_UNIFIED_INIT: { 26963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory)) 27063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int identSize = in.readInt(); 27163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (int i = 0; i < identSize; i++) { 27263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkIdentitySet ident = new NetworkIdentitySet(in); 27363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 27463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int size = in.readInt(); 27563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (int j = 0; j < size; j++) { 27663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int uid = in.readInt(); 27763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int set = in.readInt(); 27863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int tag = in.readInt(); 27963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 28063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final Key key = new Key(ident, uid, set, tag); 28163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory history = new NetworkStatsHistory(in); 28263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey recordHistory(key, history); 28363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 28463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 28563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey break; 28663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 28763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey default: { 28863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey throw new ProtocolException("unexpected version: " + version); 28963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 29063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 29163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 29263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 29363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void write(DataOutputStream out) throws IOException { 29463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // cluster key lists grouped by ident 29563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final HashMap<NetworkIdentitySet, ArrayList<Key>> keysByIdent = Maps.newHashMap(); 29663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (Key key : mStats.keySet()) { 29763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey ArrayList<Key> keys = keysByIdent.get(key.ident); 29863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (keys == null) { 29963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey keys = Lists.newArrayList(); 30063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey keysByIdent.put(key.ident, keys); 30163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 30263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey keys.add(key); 30363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 30463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 30563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(FILE_MAGIC); 30663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(VERSION_UNIFIED_INIT); 30763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 30863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(keysByIdent.size()); 30963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (NetworkIdentitySet ident : keysByIdent.keySet()) { 31063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final ArrayList<Key> keys = keysByIdent.get(ident); 31163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey ident.writeToStream(out); 31263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 31363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(keys.size()); 31463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (Key key : keys) { 31563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory history = mStats.get(key); 31663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(key.uid); 31763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(key.set); 31863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeInt(key.tag); 31963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey history.writeToStream(out); 32063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 32163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 32263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 32363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.flush(); 32463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 32563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 32663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey @Deprecated 32763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void readLegacyNetwork(File file) throws IOException { 32863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final AtomicFile inputFile = new AtomicFile(file); 32963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 33063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey DataInputStream in = null; 33163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey try { 33263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey in = new DataInputStream(new BufferedInputStream(inputFile.openRead())); 33363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 33463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // verify file magic header intact 33563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int magic = in.readInt(); 33663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (magic != FILE_MAGIC) { 33763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey throw new ProtocolException("unexpected magic: " + magic); 33863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 33963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 34063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int version = in.readInt(); 34163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey switch (version) { 34263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey case VERSION_NETWORK_INIT: { 34363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // network := size *(NetworkIdentitySet NetworkStatsHistory) 34463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int size = in.readInt(); 34563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (int i = 0; i < size; i++) { 34663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkIdentitySet ident = new NetworkIdentitySet(in); 34763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory history = new NetworkStatsHistory(in); 34863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 34963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final Key key = new Key(ident, UID_ALL, SET_ALL, TAG_NONE); 35063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey recordHistory(key, history); 35163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 35263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey break; 35363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 35463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey default: { 35563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey throw new ProtocolException("unexpected version: " + version); 35663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 35763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 35863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } catch (FileNotFoundException e) { 35963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // missing stats is okay, probably first boot 36063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } finally { 36163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey IoUtils.closeQuietly(in); 36263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 36363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 36463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 36563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey @Deprecated 36663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void readLegacyUid(File file, boolean onlyTags) throws IOException { 36763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final AtomicFile inputFile = new AtomicFile(file); 36863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 36963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey DataInputStream in = null; 37063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey try { 37163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey in = new DataInputStream(new BufferedInputStream(inputFile.openRead())); 37263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 37363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // verify file magic header intact 37463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int magic = in.readInt(); 37563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (magic != FILE_MAGIC) { 37663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey throw new ProtocolException("unexpected magic: " + magic); 37763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 37863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 37963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int version = in.readInt(); 38063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey switch (version) { 38163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey case VERSION_UID_INIT: { 38263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // uid := size *(UID NetworkStatsHistory) 38363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 38463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // drop this data version, since we don't have a good 38563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // mapping into NetworkIdentitySet. 38663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey break; 38763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 38863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey case VERSION_UID_WITH_IDENT: { 38963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory)) 39063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 39163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // drop this data version, since this version only existed 39263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // for a short time. 39363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey break; 39463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 39563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey case VERSION_UID_WITH_TAG: 39663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey case VERSION_UID_WITH_SET: { 39763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory)) 39863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int identSize = in.readInt(); 39963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (int i = 0; i < identSize; i++) { 40063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkIdentitySet ident = new NetworkIdentitySet(in); 40163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 40263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int size = in.readInt(); 40363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (int j = 0; j < size; j++) { 40463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int uid = in.readInt(); 40563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int set = (version >= VERSION_UID_WITH_SET) ? in.readInt() 40663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey : SET_DEFAULT; 40763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final int tag = in.readInt(); 40863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 40963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final Key key = new Key(ident, uid, set, tag); 41063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory history = new NetworkStatsHistory(in); 41163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 41263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if ((tag == TAG_NONE) != onlyTags) { 41363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey recordHistory(key, history); 41463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 41563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 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 /** 43163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Remove any {@link NetworkStatsHistory} attributed to the requested UID, 43263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * moving any {@link NetworkStats#TAG_NONE} series to 43363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * {@link TrafficStats#UID_REMOVED}. 43463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 435daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey public void removeUids(int[] uids) { 43663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final ArrayList<Key> knownKeys = Lists.newArrayList(); 43763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey knownKeys.addAll(mStats.keySet()); 43863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 43963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // migrate all UID stats into special "removed" bucket 44063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (Key key : knownKeys) { 441daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey if (ArrayUtils.contains(uids, key.uid)) { 44263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // only migrate combined TAG_NONE history 44363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (key.tag == TAG_NONE) { 44463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory uidHistory = mStats.get(key); 44563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory removedHistory = findOrCreateHistory( 44663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey key.ident, UID_REMOVED, SET_DEFAULT, TAG_NONE); 44763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey removedHistory.recordEntireHistory(uidHistory); 44863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 44963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mStats.remove(key); 45063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mDirty = true; 45163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 45263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 45363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 45463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 45563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private void noteRecordedHistory(long startMillis, long endMillis, long totalBytes) { 45663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (startMillis < mStartMillis) mStartMillis = startMillis; 45763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (endMillis > mEndMillis) mEndMillis = endMillis; 45863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTotalBytes += totalBytes; 45963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mDirty = true; 46063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 46163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 46263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private int estimateBuckets() { 46363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return (int) (Math.min(mEndMillis - mStartMillis, DateUtils.WEEK_IN_MILLIS * 5) 46463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey / mBucketDuration); 46563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 46663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 46763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void dump(IndentingPrintWriter pw) { 46863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final ArrayList<Key> keys = Lists.newArrayList(); 46963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey keys.addAll(mStats.keySet()); 47063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey Collections.sort(keys); 47163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 47263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (Key key : keys) { 47363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.print("ident="); pw.print(key.ident.toString()); 47463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.print(" uid="); pw.print(key.uid); 47563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.print(" set="); pw.print(NetworkStats.setToString(key.set)); 47663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.print(" tag="); pw.println(NetworkStats.tagToString(key.tag)); 47763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 47863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsHistory history = mStats.get(key); 47963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.increaseIndent(); 48063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey history.dump(pw, true); 48163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.decreaseIndent(); 48263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 48363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 48463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 48563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 48663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity} 48763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * in the given {@link NetworkIdentitySet}. 48863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 48963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static boolean templateMatches(NetworkTemplate template, NetworkIdentitySet identSet) { 49063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (NetworkIdentity ident : identSet) { 49163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (template.matches(ident)) { 49263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return true; 49363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 49463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 49563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return false; 49663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 49763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 49863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static class Key implements Comparable<Key> { 49963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public final NetworkIdentitySet ident; 50063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public final int uid; 50163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public final int set; 50263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public final int tag; 50363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 50463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final int hashCode; 50563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 50663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public Key(NetworkIdentitySet ident, int uid, int set, int tag) { 50763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey this.ident = ident; 50863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey this.uid = uid; 50963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey this.set = set; 51063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey this.tag = tag; 51163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey hashCode = Objects.hashCode(ident, uid, set, tag); 51263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 51363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 51463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey @Override 51563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public int hashCode() { 51663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return hashCode; 51763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 51863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 51963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey @Override 52063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public boolean equals(Object obj) { 52163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (obj instanceof Key) { 52263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final Key key = (Key) obj; 52363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return uid == key.uid && set == key.set && tag == key.tag 52463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey && Objects.equal(ident, key.ident); 52563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 52663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return false; 52763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 52863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 529bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 53063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public int compareTo(Key another) { 53163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return Integer.compare(uid, another.uid); 53263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 53363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 53463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey} 535