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; 23f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey 2463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull; 2563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 264ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidsonimport android.annotation.Nullable; 2763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkStats; 2863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkStats.NonMonotonicObserver; 2963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkStatsHistory; 3063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.NetworkTemplate; 3163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.TrafficStats; 32f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkeyimport android.os.Binder; 336de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkeyimport android.os.DropBoxManager; 34da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onukiimport android.service.NetworkStatsRecorderProto; 3563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.util.Log; 36ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkeyimport android.util.MathUtils; 3763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.util.Slog; 38da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onukiimport android.util.proto.ProtoOutputStream; 3963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 40f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tongimport com.android.internal.net.VpnInfo; 4163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.FileRotator; 4263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 43f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey 44f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkeyimport libcore.io.IoUtils; 45f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey 4663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.google.android.collect.Sets; 4763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 486de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkeyimport java.io.ByteArrayOutputStream; 4963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.DataOutputStream; 5063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.File; 5163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.IOException; 5263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.InputStream; 5363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.io.OutputStream; 5455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkeyimport java.io.PrintWriter; 5563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.lang.ref.WeakReference; 56daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkeyimport java.util.Arrays; 5763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.util.HashSet; 5863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport java.util.Map; 5963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 6063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey/** 6163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Logic to record deltas between periodic {@link NetworkStats} snapshots into 6263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * {@link NetworkStatsHistory} that belong to {@link NetworkStatsCollection}. 6363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Keeps pending changes in memory until they pass a specific threshold, in 64cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado * bytes. Uses {@link FileRotator} for persistence logic if present. 6563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * <p> 6663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Not inherently thread safe. 6763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 6863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeypublic class NetworkStatsRecorder { 6963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static final String TAG = "NetworkStatsRecorder"; 70e7bb71d26943fbb053139e1e34203df4c2afaa9bJeff Sharkey private static final boolean LOGD = false; 711f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey private static final boolean LOGV = false; 7263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 736de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey private static final String TAG_NETSTATS_DUMP = "netstats_dump"; 746de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey 756de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey /** Dump before deleting in {@link #recoverFromWtf()}. */ 766de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey private static final boolean DUMP_BEFORE_DELETE = true; 776de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey 7863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final FileRotator mRotator; 7963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final NonMonotonicObserver<String> mObserver; 806de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey private final DropBoxManager mDropBox; 8163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final String mCookie; 8263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 8363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final long mBucketDuration; 8463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final boolean mOnlyTags; 8563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 86ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey private long mPersistThresholdBytes = 2 * MB_IN_BYTES; 8763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private NetworkStats mLastSnapshot; 8863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 8963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final NetworkStatsCollection mPending; 9063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final NetworkStatsCollection mSinceBoot; 9163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 9263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final CombiningRewriter mPendingRewriter; 9363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 9463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private WeakReference<NetworkStatsCollection> mComplete; 9563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 96cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado /** 97cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado * Non-persisted recorder, with only one bucket. Used by {@link NetworkStatsObservers}. 98cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado */ 99cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado public NetworkStatsRecorder() { 100cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mRotator = null; 101cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mObserver = null; 102cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mDropBox = null; 103cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mCookie = null; 104cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 105cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado // set the bucket big enough to have all data in one bucket, but allow some 106cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado // slack to avoid overflow 107cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mBucketDuration = YEAR_IN_MILLIS; 108cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mOnlyTags = false; 109cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 110cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mPending = null; 111cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mSinceBoot = new NetworkStatsCollection(mBucketDuration); 112cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 113cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mPendingRewriter = null; 114cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 115cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 116cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado /** 117cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado * Persisted recorder. 118cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado */ 11963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver<String> observer, 1206de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags) { 12163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator = checkNotNull(rotator, "missing FileRotator"); 12263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mObserver = checkNotNull(observer, "missing NonMonotonicObserver"); 1236de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey mDropBox = checkNotNull(dropBox, "missing DropBoxManager"); 12463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mCookie = cookie; 12563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 12663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mBucketDuration = bucketDuration; 12763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mOnlyTags = onlyTags; 12863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 12963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mPending = new NetworkStatsCollection(bucketDuration); 13063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mSinceBoot = new NetworkStatsCollection(bucketDuration); 13163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 13263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mPendingRewriter = new CombiningRewriter(mPending); 13363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 13463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 135ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey public void setPersistThreshold(long thresholdBytes) { 136ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey if (LOGV) Slog.v(TAG, "setPersistThreshold() with " + thresholdBytes); 137ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey mPersistThresholdBytes = MathUtils.constrain( 138ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey thresholdBytes, 1 * KB_IN_BYTES, 100 * MB_IN_BYTES); 139ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey } 140ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey 14163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void resetLocked() { 14263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mLastSnapshot = null; 143cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mPending != null) { 144cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mPending.reset(); 145cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 146cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mSinceBoot != null) { 147cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mSinceBoot.reset(); 148cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 149cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mComplete != null) { 150cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mComplete.clear(); 151cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 15263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 15363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 15463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStats.Entry getTotalSinceBootLocked(NetworkTemplate template) { 1551efb1335814aea8ee0696144ca0ab24159b86e54Jeff Davidson return mSinceBoot.getSummary(template, Long.MIN_VALUE, Long.MAX_VALUE, 156f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotal(null); 15763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 15863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 159cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado public NetworkStatsCollection getSinceBoot() { 160cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado return mSinceBoot; 161cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 162cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 16363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 16463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Load complete history represented by {@link FileRotator}. Caches 16563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * internally as a {@link WeakReference}, and updated with future 16663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * {@link #recordSnapshotLocked(NetworkStats, Map, long)} snapshots as long 16763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * as reference is valid. 16863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 16963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStatsCollection getOrLoadCompleteLocked() { 170cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado checkNotNull(mRotator, "missing FileRotator"); 17155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey NetworkStatsCollection res = mComplete != null ? mComplete.get() : null; 17255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (res == null) { 17355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey res = loadLocked(Long.MIN_VALUE, Long.MAX_VALUE); 17455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey mComplete = new WeakReference<NetworkStatsCollection>(res); 17563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 17655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey return res; 17755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 17855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 17955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey public NetworkStatsCollection getOrLoadPartialLocked(long start, long end) { 180cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado checkNotNull(mRotator, "missing FileRotator"); 18155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey NetworkStatsCollection res = mComplete != null ? mComplete.get() : null; 18255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (res == null) { 18355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey res = loadLocked(start, end); 18455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 18555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey return res; 18655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 18755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 18855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey private NetworkStatsCollection loadLocked(long start, long end) { 18955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (LOGD) Slog.d(TAG, "loadLocked() reading from disk for " + mCookie); 19055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final NetworkStatsCollection res = new NetworkStatsCollection(mBucketDuration); 19155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey try { 19255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey mRotator.readMatching(res, start, end); 19355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey res.recordCollection(mPending); 19455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } catch (IOException e) { 19555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey Log.wtf(TAG, "problem completely reading network stats", e); 19655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey recoverFromWtf(); 19755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } catch (OutOfMemoryError e) { 19855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey Log.wtf(TAG, "problem completely reading network stats", e); 19955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey recoverFromWtf(); 20055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 20155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey return res; 20263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 20363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 20463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 20563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Record any delta that occurred since last {@link NetworkStats} snapshot, 20663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * using the given {@link Map} to identify network interfaces. First 20763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * snapshot is considered bootstrap, and is not counted as delta. 2084ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidson * 2094ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidson * @param vpnArray Optional info about the currently active VPN, if any. This is used to 2104ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidson * redistribute traffic from the VPN app to the underlying responsible apps. 2114ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidson * This should always be set to null if the provided snapshot is aggregated 2124ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidson * across all UIDs (e.g. contains UID_ALL buckets), regardless of VPN state. 21363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 21463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void recordSnapshotLocked(NetworkStats snapshot, 2154ff3bcfa0c143ad14c81d07f90ed6dc375701ab1Jeff Davidson Map<String, NetworkIdentitySet> ifaceIdent, @Nullable VpnInfo[] vpnArray, 216f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong long currentTimeMillis) { 21763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final HashSet<String> unknownIfaces = Sets.newHashSet(); 21863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 219e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey // skip recording when snapshot missing 220e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey if (snapshot == null) return; 221e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey 22263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // assume first snapshot is bootstrap and don't record 22363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (mLastSnapshot == null) { 22463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mLastSnapshot = snapshot; 22563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return; 22663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 22763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 22863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null; 22963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 23063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStats delta = NetworkStats.subtract( 23163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey snapshot, mLastSnapshot, mObserver, mCookie); 23263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long end = currentTimeMillis; 23363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long start = end - delta.getElapsedRealtime(); 23463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 235f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong if (vpnArray != null) { 236f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong for (VpnInfo info : vpnArray) { 237f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface); 238f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong } 239f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong } 240f5ea340aabee6e290448c8cc9fb0925da8b7db5eWenchao Tong 24163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey NetworkStats.Entry entry = null; 24263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey for (int i = 0; i < delta.size(); i++) { 24363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey entry = delta.getValues(i, entry); 244b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey 245b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey // As a last-ditch sanity check, report any negative values and 246b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey // clamp them so recording below doesn't croak. 247b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey if (entry.isNegative()) { 248b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey if (mObserver != null) { 249b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey mObserver.foundNonMonotonic(delta, i, mCookie); 250b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey } 251b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey entry.rxBytes = Math.max(entry.rxBytes, 0); 252b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey entry.rxPackets = Math.max(entry.rxPackets, 0); 253b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey entry.txBytes = Math.max(entry.txBytes, 0); 254b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey entry.txPackets = Math.max(entry.txPackets, 0); 255b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey entry.operations = Math.max(entry.operations, 0); 256b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey } 257b5a97e6f63bfe8b828224f606f8cb8585d9f28ecJeff Sharkey 25863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkIdentitySet ident = ifaceIdent.get(entry.iface); 25963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (ident == null) { 26063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey unknownIfaces.add(entry.iface); 26163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey continue; 26263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 26363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 264ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey // skip when no delta occurred 26563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (entry.isEmpty()) continue; 26663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 26763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // only record tag data when requested 26863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if ((entry.tag == TAG_NONE) != mOnlyTags) { 269cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mPending != null) { 270cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mPending.recordData(ident, entry.uid, entry.set, entry.tag, start, end, entry); 271cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 27263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 27363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // also record against boot stats when present 27463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (mSinceBoot != null) { 27563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mSinceBoot.recordData(ident, entry.uid, entry.set, entry.tag, start, end, entry); 27663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 27763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 27863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // also record against complete dataset when present 27963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (complete != null) { 28063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey complete.recordData(ident, entry.uid, entry.set, entry.tag, start, end, entry); 28163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 28263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 28363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 28463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 28563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mLastSnapshot = snapshot; 28663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 2871f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey if (LOGV && unknownIfaces.size() > 0) { 28863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey Slog.w(TAG, "unknown interfaces " + unknownIfaces + ", ignoring those stats"); 28963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 29063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 29163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 29263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 29363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Consider persisting any pending deltas, if they are beyond 29463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * {@link #mPersistThresholdBytes}. 29563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 29663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void maybePersistLocked(long currentTimeMillis) { 297cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado checkNotNull(mRotator, "missing FileRotator"); 29863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long pendingBytes = mPending.getTotalBytes(); 29963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (pendingBytes >= mPersistThresholdBytes) { 30063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey forcePersistLocked(currentTimeMillis); 30163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } else { 30263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.maybeRotate(currentTimeMillis); 30363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 30463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 30563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 30663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 30763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Force persisting any pending deltas. 30863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 30963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void forcePersistLocked(long currentTimeMillis) { 310cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado checkNotNull(mRotator, "missing FileRotator"); 31163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (mPending.isDirty()) { 31263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (LOGD) Slog.d(TAG, "forcePersistLocked() writing for " + mCookie); 31363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey try { 31463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.rewriteActive(mPendingRewriter, currentTimeMillis); 31563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.maybeRotate(currentTimeMillis); 31663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mPending.reset(); 31763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } catch (IOException e) { 31863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey Log.wtf(TAG, "problem persisting pending stats", e); 3196de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey recoverFromWtf(); 320e4984bea95a07dea0ef0259fefa1e52f0bbb1533Jeff Sharkey } catch (OutOfMemoryError e) { 321e4984bea95a07dea0ef0259fefa1e52f0bbb1533Jeff Sharkey Log.wtf(TAG, "problem persisting pending stats", e); 322e4984bea95a07dea0ef0259fefa1e52f0bbb1533Jeff Sharkey recoverFromWtf(); 32363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 32463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 32563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 32663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 32763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 32863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Remove the given UID from all {@link FileRotator} history, migrating it 32963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * to {@link TrafficStats#UID_REMOVED}. 33063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 331daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey public void removeUidsLocked(int[] uids) { 332cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mRotator != null) { 333cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado try { 334cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado // Rewrite all persisted data to migrate UID stats 335cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mRotator.rewriteAll(new RemoveUidRewriter(mBucketDuration, uids)); 336cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } catch (IOException e) { 337cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado Log.wtf(TAG, "problem removing UIDs " + Arrays.toString(uids), e); 338cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado recoverFromWtf(); 339cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } catch (OutOfMemoryError e) { 340cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado Log.wtf(TAG, "problem removing UIDs " + Arrays.toString(uids), e); 341cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado recoverFromWtf(); 342cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 34363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 34463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 345daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey // Remove any pending stats 346cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mPending != null) { 347cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mPending.removeUids(uids); 348cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 349cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mSinceBoot != null) { 350cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado mSinceBoot.removeUids(uids); 351cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 352daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey 353daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey // Clear UID from current stats snapshot 35463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (mLastSnapshot != null) { 355daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey mLastSnapshot = mLastSnapshot.withoutUids(uids); 35663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 357b52e3e55098c4a6e3dbfe19885895411cfb38911Jeff Sharkey 358b52e3e55098c4a6e3dbfe19885895411cfb38911Jeff Sharkey final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null; 359b52e3e55098c4a6e3dbfe19885895411cfb38911Jeff Sharkey if (complete != null) { 360daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey complete.removeUids(uids); 361b52e3e55098c4a6e3dbfe19885895411cfb38911Jeff Sharkey } 36263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 36363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 36463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 36563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Rewriter that will combine current {@link NetworkStatsCollection} values 36663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * with anything read from disk, and write combined set to disk. Clears the 36763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * original {@link NetworkStatsCollection} when finished writing. 36863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 36963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private static class CombiningRewriter implements FileRotator.Rewriter { 37063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final NetworkStatsCollection mCollection; 37163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 37263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public CombiningRewriter(NetworkStatsCollection collection) { 37363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mCollection = checkNotNull(collection, "missing NetworkStatsCollection"); 37463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 37563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 376bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 37763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void reset() { 37863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // ignored 37963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 38063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 381bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 38263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void read(InputStream in) throws IOException { 38363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mCollection.read(in); 38463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 38563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 386bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 38763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public boolean shouldWrite() { 38863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return true; 38963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 39063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 391bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 39263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void write(OutputStream out) throws IOException { 39363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mCollection.write(new DataOutputStream(out)); 39463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mCollection.reset(); 39563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 39663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 39763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 39863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 39963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Rewriter that will remove any {@link NetworkStatsHistory} attributed to 40063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * the requested UID, only writing data back when modified. 40163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 40263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public static class RemoveUidRewriter implements FileRotator.Rewriter { 40363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private final NetworkStatsCollection mTemp; 404daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey private final int[] mUids; 40563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 406daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey public RemoveUidRewriter(long bucketDuration, int[] uids) { 40763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTemp = new NetworkStatsCollection(bucketDuration); 408daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey mUids = uids; 40963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 41063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 411bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 41263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void reset() { 41363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTemp.reset(); 41463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 41563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 416bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 41763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void read(InputStream in) throws IOException { 41863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTemp.read(in); 41963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTemp.clearDirty(); 420daa57e8d1866fe4579c280c41604f3660db7cd01Jeff Sharkey mTemp.removeUids(mUids); 42163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 42263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 423bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 42463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public boolean shouldWrite() { 42563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return mTemp.isDirty(); 42663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 42763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 428bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 42963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void write(OutputStream out) throws IOException { 43063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mTemp.write(new DataOutputStream(out)); 43163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 43263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 43363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 43463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void importLegacyNetworkLocked(File file) throws IOException { 435cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado checkNotNull(mRotator, "missing FileRotator"); 436cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 43763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // legacy file still exists; start empty to avoid double importing 43863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.deleteAll(); 43963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 44063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration); 44163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey collection.readLegacyNetwork(file); 44263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 44363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long startMillis = collection.getStartMillis(); 44463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long endMillis = collection.getEndMillis(); 44563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 44663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (!collection.isEmpty()) { 44763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // process legacy data, creating active file at starting time, then 44863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // using end time to possibly trigger rotation. 44963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.rewriteActive(new CombiningRewriter(collection), startMillis); 45063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.maybeRotate(endMillis); 45163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 45263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 45363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 45463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void importLegacyUidLocked(File file) throws IOException { 455cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado checkNotNull(mRotator, "missing FileRotator"); 456cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado 45763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // legacy file still exists; start empty to avoid double importing 45863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.deleteAll(); 45963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 46063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration); 46163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey collection.readLegacyUid(file, mOnlyTags); 46263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 46363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long startMillis = collection.getStartMillis(); 46463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long endMillis = collection.getEndMillis(); 46563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 46663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (!collection.isEmpty()) { 46763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // process legacy data, creating active file at starting time, then 46863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // using end time to possibly trigger rotation. 46963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.rewriteActive(new CombiningRewriter(collection), startMillis); 47063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mRotator.maybeRotate(endMillis); 47163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 47263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 47363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 47463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void dumpLocked(IndentingPrintWriter pw, boolean fullHistory) { 475cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado if (mPending != null) { 476cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado pw.print("Pending bytes: "); pw.println(mPending.getTotalBytes()); 477cd42acd9515bdce89d4f1401ee2888d684bf1918Antonio Cansado } 47863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (fullHistory) { 47963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.println("Complete history:"); 48063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey getOrLoadCompleteLocked().dump(pw); 48163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } else { 48263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.println("History since boot:"); 48363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey mSinceBoot.dump(pw); 48463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 48563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 4866de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey 487da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki public void writeToProtoLocked(ProtoOutputStream proto, long tag) { 488da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki final long start = proto.start(tag); 489da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki if (mPending != null) { 490da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki proto.write(NetworkStatsRecorderProto.PENDING_TOTAL_BYTES, mPending.getTotalBytes()); 491da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki } 492da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki getOrLoadCompleteLocked().writeToProto(proto, NetworkStatsRecorderProto.COMPLETE_HISTORY); 493da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki proto.end(start); 494da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki } 495da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki 49655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey public void dumpCheckin(PrintWriter pw, long start, long end) { 49755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey // Only load and dump stats from the requested window 49855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey getOrLoadPartialLocked(start, end).dumpCheckin(pw, start, end); 49955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 50055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 5016de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey /** 5026de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey * Recover from {@link FileRotator} failure by dumping state to 5036de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey * {@link DropBoxManager} and deleting contents. 5046de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey */ 5056de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey private void recoverFromWtf() { 5066de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey if (DUMP_BEFORE_DELETE) { 5076de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey final ByteArrayOutputStream os = new ByteArrayOutputStream(); 5086de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey try { 5096de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey mRotator.dumpAll(os); 5106de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey } catch (IOException e) { 5116de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey // ignore partial contents 5126de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey os.reset(); 5136de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey } finally { 5146de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey IoUtils.closeQuietly(os); 5156de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey } 5166de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey mDropBox.addData(TAG_NETSTATS_DUMP, os.toByteArray(), 0); 5176de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey } 5186de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey 5196de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey mRotator.deleteAll(); 5206de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey } 52163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey} 522