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.TAG_NONE; 20ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkeyimport static android.net.TrafficStats.KB_IN_BYTES; 21ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkeyimport static android.net.TrafficStats.MB_IN_BYTES; 22cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansadoimport static android.text.format.DateUtils.YEAR_IN_MILLIS; 2363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull; 2463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 254ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidsonimport android.annotation.Nullable; 2663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkStats; 2763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkStats.NonMonotonicObserver; 2863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkStatsHistory; 2963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkTemplate; 3063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.TrafficStats; 316de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkeyimport android.os.DropBoxManager; 3263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.util.Log; 33ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkeyimport android.util.MathUtils; 3463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.util.Slog; 3563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 36f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tongimport com.android.internal.net.VpnInfo; 3763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.FileRotator; 3863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 3963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.google.android.collect.Sets; 4063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 416de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkeyimport java.io.ByteArrayOutputStream; 4263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.DataOutputStream; 4363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.File; 4463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.IOException; 4563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.InputStream; 4663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.OutputStream; 4755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkeyimport java.io.PrintWriter; 4863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.lang.ref.WeakReference; 49daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkeyimport java.util.Arrays; 5063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.util.HashSet; 5163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.util.Map; 5263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 536de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkeyimport libcore.io.IoUtils; 546de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey 5563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey/** 5663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Logic to record deltas between periodic {@link NetworkStats} snapshots into 5763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * {@link NetworkStatsHistory} that belong to {@link NetworkStatsCollection}. 5863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Keeps pending changes in memory until they pass a specific threshold, in 59cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado * bytes. Uses {@link FileRotator} for persistence logic if present. 6063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * <p> 6163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Not inherently thread safe. 6263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 6363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeypublic class NetworkStatsRecorder { 6463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final String TAG = "NetworkStatsRecorder"; 65e7bb71d26943fbb053139e1e34203df4c2afaa9bJeff Sharkey private static final boolean LOGD = false; 661f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey private static final boolean LOGV = false; 6763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 686de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey private static final String TAG_NETSTATS_DUMP = "netstats_dump"; 696de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey 706de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey /** Dump before deleting in {@link #recoverFromWtf()}. */ 716de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey private static final boolean DUMP_BEFORE_DELETE = true; 726de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey 7363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final FileRotator mRotator; 7463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final NonMonotonicObserver<String> mObserver; 756de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey private final DropBoxManager mDropBox; 7663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final String mCookie; 7763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 7863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final long mBucketDuration; 7963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final boolean mOnlyTags; 8063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 81ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey private long mPersistThresholdBytes = 2 * MB_IN_BYTES; 8263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private NetworkStats mLastSnapshot; 8363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 8463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final NetworkStatsCollection mPending; 8563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final NetworkStatsCollection mSinceBoot; 8663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 8763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final CombiningRewriter mPendingRewriter; 8863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 8963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private WeakReference<NetworkStatsCollection> mComplete; 9063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 91cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado /** 92cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado * Non-persisted recorder, with only one bucket. Used by {@link NetworkStatsObservers}. 93cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado */ 94cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado public NetworkStatsRecorder() { 95cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mRotator = null; 96cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mObserver = null; 97cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mDropBox = null; 98cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mCookie = null; 99cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 100cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado // set the bucket big enough to have all data in one bucket, but allow some 101cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado // slack to avoid overflow 102cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mBucketDuration = YEAR_IN_MILLIS; 103cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mOnlyTags = false; 104cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 105cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mPending = null; 106cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mSinceBoot = new NetworkStatsCollection(mBucketDuration); 107cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 108cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mPendingRewriter = null; 109cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 110cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 111cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado /** 112cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado * Persisted recorder. 113cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado */ 11463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver<String> observer, 1156de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags) { 11663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator = checkNotNull(rotator, "missing FileRotator"); 11763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mObserver = checkNotNull(observer, "missing NonMonotonicObserver"); 1186de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey mDropBox = checkNotNull(dropBox, "missing DropBoxManager"); 11963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mCookie = cookie; 12063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 12163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mBucketDuration = bucketDuration; 12263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mOnlyTags = onlyTags; 12363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 12463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mPending = new NetworkStatsCollection(bucketDuration); 12563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mSinceBoot = new NetworkStatsCollection(bucketDuration); 12663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 12763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mPendingRewriter = new CombiningRewriter(mPending); 12863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 12963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 130ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey public void setPersistThreshold(long thresholdBytes) { 131ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey if (LOGV) Slog.v(TAG, "setPersistThreshold() with " + thresholdBytes); 132ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey mPersistThresholdBytes = MathUtils.constrain( 133ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey thresholdBytes, 1 * KB_IN_BYTES, 100 * MB_IN_BYTES); 134ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey } 135ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey 13663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void resetLocked() { 13763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mLastSnapshot = null; 138cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mPending != null) { 139cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mPending.reset(); 140cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 141cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mSinceBoot != null) { 142cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mSinceBoot.reset(); 143cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 144cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mComplete != null) { 145cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mComplete.clear(); 146cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 14763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 14863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 14963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStats.Entry getTotalSinceBootLocked(NetworkTemplate template) { 1501efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson return mSinceBoot.getSummary(template, Long.MIN_VALUE, Long.MAX_VALUE, 1511efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson NetworkStatsAccess.Level.DEVICE).getTotal(null); 15263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 15363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 154cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado public NetworkStatsCollection getSinceBoot() { 155cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado return mSinceBoot; 156cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 157cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 15863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 15963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Load complete history represented by {@link FileRotator}. Caches 16063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * internally as a {@link WeakReference}, and updated with future 16163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * {@link #recordSnapshotLocked(NetworkStats, Map, long)} snapshots as long 16263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * as reference is valid. 16363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 16463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStatsCollection getOrLoadCompleteLocked() { 165cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado checkNotNull(mRotator, "missing FileRotator"); 16655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey NetworkStatsCollection res = mComplete != null ? mComplete.get() : null; 16755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (res == null) { 16855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey res = loadLocked(Long.MIN_VALUE, Long.MAX_VALUE); 16955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey mComplete = new WeakReference<NetworkStatsCollection>(res); 17063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 17155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey return res; 17255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 17355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 17455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey public NetworkStatsCollection getOrLoadPartialLocked(long start, long end) { 175cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado checkNotNull(mRotator, "missing FileRotator"); 17655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey NetworkStatsCollection res = mComplete != null ? mComplete.get() : null; 17755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (res == null) { 17855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey res = loadLocked(start, end); 17955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 18055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey return res; 18155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 18255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 18355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey private NetworkStatsCollection loadLocked(long start, long end) { 18455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (LOGD) Slog.d(TAG, "loadLocked() reading from disk for " + mCookie); 18555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final NetworkStatsCollection res = new NetworkStatsCollection(mBucketDuration); 18655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey try { 18755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey mRotator.readMatching(res, start, end); 18855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey res.recordCollection(mPending); 18955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } catch (IOException e) { 19055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey Log.wtf(TAG, "problem completely reading network stats", e); 19155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey recoverFromWtf(); 19255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } catch (OutOfMemoryError e) { 19355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey Log.wtf(TAG, "problem completely reading network stats", e); 19455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey recoverFromWtf(); 19555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 19655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey return res; 19763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 19863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 19963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 20063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Record any delta that occurred since last {@link NetworkStats} snapshot, 20163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * using the given {@link Map} to identify network interfaces. First 20263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * snapshot is considered bootstrap, and is not counted as delta. 2034ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidson * 2044ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidson * @param vpnArray Optional info about the currently active VPN, if any. This is used to 2054ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidson * redistribute traffic from the VPN app to the underlying responsible apps. 2064ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidson * This should always be set to null if the provided snapshot is aggregated 2074ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidson * across all UIDs (e.g. contains UID_ALL buckets), regardless of VPN state. 20863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 20963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void recordSnapshotLocked(NetworkStats snapshot, 2104ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidson Map<String, NetworkIdentitySet> ifaceIdent, @Nullable VpnInfo[] vpnArray, 211f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong long currentTimeMillis) { 21263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final HashSet<String> unknownIfaces = Sets.newHashSet(); 21363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 214e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey // skip recording when snapshot missing 215e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey if (snapshot == null) return; 216e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey 21763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // assume first snapshot is bootstrap and don't record 21863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (mLastSnapshot == null) { 21963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mLastSnapshot = snapshot; 22063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return; 22163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 22263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 22363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null; 22463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 22563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStats delta = NetworkStats.subtract( 22663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey snapshot, mLastSnapshot, mObserver, mCookie); 22763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long end = currentTimeMillis; 22863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long start = end - delta.getElapsedRealtime(); 22963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 230f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong if (vpnArray != null) { 231f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong for (VpnInfo info : vpnArray) { 232f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface); 233f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong } 234f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong } 235f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong 23663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey NetworkStats.Entry entry = null; 23763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (int i = 0; i < delta.size(); i++) { 23863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry = delta.getValues(i, entry); 23963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkIdentitySet ident = ifaceIdent.get(entry.iface); 24063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (ident == null) { 24163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey unknownIfaces.add(entry.iface); 24263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey continue; 24363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 24463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 245ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey // skip when no delta occurred 24663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (entry.isEmpty()) continue; 24763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 24863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // only record tag data when requested 24963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if ((entry.tag == TAG_NONE) != mOnlyTags) { 250cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mPending != null) { 251cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mPending.recordData(ident, entry.uid, entry.set, entry.tag, start, end, entry); 252cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 25363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 25463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // also record against boot stats when present 25563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (mSinceBoot != null) { 25663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mSinceBoot.recordData(ident, entry.uid, entry.set, entry.tag, start, end, entry); 25763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 25863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 25963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // also record against complete dataset when present 26063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (complete != null) { 26163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey complete.recordData(ident, entry.uid, entry.set, entry.tag, start, end, entry); 26263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 26363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 26463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 26563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 26663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mLastSnapshot = snapshot; 26763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 2681f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey if (LOGV && unknownIfaces.size() > 0) { 26963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey Slog.w(TAG, "unknown interfaces " + unknownIfaces + ", ignoring those stats"); 27063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 27163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 27263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 27363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 27463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Consider persisting any pending deltas, if they are beyond 27563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * {@link #mPersistThresholdBytes}. 27663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 27763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void maybePersistLocked(long currentTimeMillis) { 278cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado checkNotNull(mRotator, "missing FileRotator"); 27963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long pendingBytes = mPending.getTotalBytes(); 28063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (pendingBytes >= mPersistThresholdBytes) { 28163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey forcePersistLocked(currentTimeMillis); 28263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } else { 28363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.maybeRotate(currentTimeMillis); 28463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 28563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 28663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 28763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 28863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Force persisting any pending deltas. 28963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 29063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void forcePersistLocked(long currentTimeMillis) { 291cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado checkNotNull(mRotator, "missing FileRotator"); 29263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (mPending.isDirty()) { 29363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (LOGD) Slog.d(TAG, "forcePersistLocked() writing for " + mCookie); 29463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey try { 29563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.rewriteActive(mPendingRewriter, currentTimeMillis); 29663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.maybeRotate(currentTimeMillis); 29763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mPending.reset(); 29863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } catch (IOException e) { 29963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey Log.wtf(TAG, "problem persisting pending stats", e); 3006de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey recoverFromWtf(); 301e4984bea95a07dea0ef0259fefa1e52f0bbb1533Jeff Sharkey } catch (OutOfMemoryError e) { 302e4984bea95a07dea0ef0259fefa1e52f0bbb1533Jeff Sharkey Log.wtf(TAG, "problem persisting pending stats", e); 303e4984bea95a07dea0ef0259fefa1e52f0bbb1533Jeff Sharkey recoverFromWtf(); 30463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 30563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 30663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 30763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 30863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 30963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Remove the given UID from all {@link FileRotator} history, migrating it 31063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * to {@link TrafficStats#UID_REMOVED}. 31163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 312daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey public void removeUidsLocked(int[] uids) { 313cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mRotator != null) { 314cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado try { 315cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado // Rewrite all persisted data to migrate UID stats 316cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mRotator.rewriteAll(new RemoveUidRewriter(mBucketDuration, uids)); 317cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } catch (IOException e) { 318cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado Log.wtf(TAG, "problem removing UIDs " + Arrays.toString(uids), e); 319cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado recoverFromWtf(); 320cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } catch (OutOfMemoryError e) { 321cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado Log.wtf(TAG, "problem removing UIDs " + Arrays.toString(uids), e); 322cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado recoverFromWtf(); 323cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 32463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 32563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 326daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey // Remove any pending stats 327cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mPending != null) { 328cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mPending.removeUids(uids); 329cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 330cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mSinceBoot != null) { 331cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mSinceBoot.removeUids(uids); 332cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 333daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey 334daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey // Clear UID from current stats snapshot 33563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (mLastSnapshot != null) { 336daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey mLastSnapshot = mLastSnapshot.withoutUids(uids); 33763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 338b52e3e55098c4a6e3dbfe19885895411cfb38911Jeff Sharkey 339b52e3e55098c4a6e3dbfe19885895411cfb38911Jeff Sharkey final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null; 340b52e3e55098c4a6e3dbfe19885895411cfb38911Jeff Sharkey if (complete != null) { 341daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey complete.removeUids(uids); 342b52e3e55098c4a6e3dbfe19885895411cfb38911Jeff Sharkey } 34363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 34463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 34563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 34663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Rewriter that will combine current {@link NetworkStatsCollection} values 34763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * with anything read from disk, and write combined set to disk. Clears the 34863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * original {@link NetworkStatsCollection} when finished writing. 34963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 35063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static class CombiningRewriter implements FileRotator.Rewriter { 35163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final NetworkStatsCollection mCollection; 35263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 35363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public CombiningRewriter(NetworkStatsCollection collection) { 35463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mCollection = checkNotNull(collection, "missing NetworkStatsCollection"); 35563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 35663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 357bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 35863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void reset() { 35963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // ignored 36063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 36163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 362bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 36363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void read(InputStream in) throws IOException { 36463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mCollection.read(in); 36563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 36663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 367bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 36863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public boolean shouldWrite() { 36963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return true; 37063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 37163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 372bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 37363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void write(OutputStream out) throws IOException { 37463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mCollection.write(new DataOutputStream(out)); 37563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mCollection.reset(); 37663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 37763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 37863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 37963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 38063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Rewriter that will remove any {@link NetworkStatsHistory} attributed to 38163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * the requested UID, only writing data back when modified. 38263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 38363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public static class RemoveUidRewriter implements FileRotator.Rewriter { 38463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final NetworkStatsCollection mTemp; 385daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey private final int[] mUids; 38663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 387daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey public RemoveUidRewriter(long bucketDuration, int[] uids) { 38863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTemp = new NetworkStatsCollection(bucketDuration); 389daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey mUids = uids; 39063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 39163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 392bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 39363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void reset() { 39463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTemp.reset(); 39563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 39663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 397bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 39863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void read(InputStream in) throws IOException { 39963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTemp.read(in); 40063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTemp.clearDirty(); 401daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey mTemp.removeUids(mUids); 40263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 40363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 404bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 40563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public boolean shouldWrite() { 40663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return mTemp.isDirty(); 40763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 40863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 409bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 41063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void write(OutputStream out) throws IOException { 41163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTemp.write(new DataOutputStream(out)); 41263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 41363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 41463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 41563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void importLegacyNetworkLocked(File file) throws IOException { 416cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado checkNotNull(mRotator, "missing FileRotator"); 417cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 41863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // legacy file still exists; start empty to avoid double importing 41963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.deleteAll(); 42063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 42163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration); 42263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey collection.readLegacyNetwork(file); 42363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 42463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long startMillis = collection.getStartMillis(); 42563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long endMillis = collection.getEndMillis(); 42663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 42763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (!collection.isEmpty()) { 42863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // process legacy data, creating active file at starting time, then 42963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // using end time to possibly trigger rotation. 43063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.rewriteActive(new CombiningRewriter(collection), startMillis); 43163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.maybeRotate(endMillis); 43263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 43363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 43463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 43563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void importLegacyUidLocked(File file) throws IOException { 436cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado checkNotNull(mRotator, "missing FileRotator"); 437cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 43863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // legacy file still exists; start empty to avoid double importing 43963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.deleteAll(); 44063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 44163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration); 44263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey collection.readLegacyUid(file, mOnlyTags); 44363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 44463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long startMillis = collection.getStartMillis(); 44563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long endMillis = collection.getEndMillis(); 44663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 44763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (!collection.isEmpty()) { 44863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // process legacy data, creating active file at starting time, then 44963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // using end time to possibly trigger rotation. 45063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.rewriteActive(new CombiningRewriter(collection), startMillis); 45163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.maybeRotate(endMillis); 45263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 45363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 45463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 45563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void dumpLocked(IndentingPrintWriter pw, boolean fullHistory) { 456cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mPending != null) { 457cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado pw.print("Pending bytes: "); pw.println(mPending.getTotalBytes()); 458cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 45963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (fullHistory) { 46063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.println("Complete history:"); 46163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey getOrLoadCompleteLocked().dump(pw); 46263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } else { 46363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.println("History since boot:"); 46463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mSinceBoot.dump(pw); 46563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 46663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 4676de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey 46855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey public void dumpCheckin(PrintWriter pw, long start, long end) { 46955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey // Only load and dump stats from the requested window 47055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey getOrLoadPartialLocked(start, end).dumpCheckin(pw, start, end); 47155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 47255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 4736de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey /** 4746de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey * Recover from {@link FileRotator} failure by dumping state to 4756de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey * {@link DropBoxManager} and deleting contents. 4766de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey */ 4776de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey private void recoverFromWtf() { 4786de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey if (DUMP_BEFORE_DELETE) { 4796de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey final ByteArrayOutputStream os = new ByteArrayOutputStream(); 4806de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey try { 4816de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey mRotator.dumpAll(os); 4826de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey } catch (IOException e) { 4836de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey // ignore partial contents 4846de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey os.reset(); 4856de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey } finally { 4866de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey IoUtils.closeQuietly(os); 4876de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey } 4886de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey mDropBox.addData(TAG_NETSTATS_DUMP, os.toByteArray(), 0); 4896de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey } 4906de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey 4916de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey mRotator.deleteAll(); 4926de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey } 49363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey} 494