Merge "[MS59.1] Add NetworkStatsDataMigrationUtils" am: c428b10a74 am: a5beb8b8f9 am: b7a3ae056c
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1951480 Change-Id: Iebc807ae214159ec696a2ebbb037bbe7234f9e88
This commit is contained in:
@@ -0,0 +1,520 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.net.netstats;
|
||||||
|
|
||||||
|
import static android.app.usage.NetworkStatsManager.PREFIX_UID;
|
||||||
|
import static android.app.usage.NetworkStatsManager.PREFIX_UID_TAG;
|
||||||
|
import static android.app.usage.NetworkStatsManager.PREFIX_XT;
|
||||||
|
import static android.net.ConnectivityManager.TYPE_MOBILE;
|
||||||
|
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
|
||||||
|
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
|
||||||
|
import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
|
||||||
|
import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
|
||||||
|
import static android.net.NetworkStats.SET_DEFAULT;
|
||||||
|
import static android.net.NetworkStats.TAG_NONE;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.net.NetworkIdentity;
|
||||||
|
import android.net.NetworkStatsCollection;
|
||||||
|
import android.net.NetworkStatsHistory;
|
||||||
|
import android.net.NetworkTemplate;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.util.AtomicFile;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.internal.util.FastDataInput;
|
||||||
|
|
||||||
|
import libcore.io.IoUtils;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.ProtocolException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to read old version of persistent network statistics, the implementation is
|
||||||
|
* intended to be modified by OEM partners to accommodate their custom changes.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
// @SystemApi(client = MODULE_LIBRARIES)
|
||||||
|
public class NetworkStatsDataMigrationUtils {
|
||||||
|
|
||||||
|
private static final HashMap<String, String> sPrefixLegacyFileNameMap =
|
||||||
|
new HashMap<String, String>() {{
|
||||||
|
put(PREFIX_XT, "netstats_xt.bin");
|
||||||
|
put(PREFIX_UID, "netstats_uid.bin");
|
||||||
|
put(PREFIX_UID_TAG, "netstats_uid.bin");
|
||||||
|
}};
|
||||||
|
|
||||||
|
// These version constants are copied from NetworkStatsCollection/History, which is okay for
|
||||||
|
// OEMs to modify to adapt their own logic.
|
||||||
|
private static class CollectionVersion {
|
||||||
|
static final int VERSION_NETWORK_INIT = 1;
|
||||||
|
|
||||||
|
static final int VERSION_UID_INIT = 1;
|
||||||
|
static final int VERSION_UID_WITH_IDENT = 2;
|
||||||
|
static final int VERSION_UID_WITH_TAG = 3;
|
||||||
|
static final int VERSION_UID_WITH_SET = 4;
|
||||||
|
|
||||||
|
static final int VERSION_UNIFIED_INIT = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class HistoryVersion {
|
||||||
|
static final int VERSION_INIT = 1;
|
||||||
|
static final int VERSION_ADD_PACKETS = 2;
|
||||||
|
static final int VERSION_ADD_ACTIVE = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class IdentitySetVersion {
|
||||||
|
static final int VERSION_INIT = 1;
|
||||||
|
static final int VERSION_ADD_ROAMING = 2;
|
||||||
|
static final int VERSION_ADD_NETWORK_ID = 3;
|
||||||
|
static final int VERSION_ADD_METERED = 4;
|
||||||
|
static final int VERSION_ADD_DEFAULT_NETWORK = 5;
|
||||||
|
static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File header magic number: "ANET". The definition is copied from NetworkStatsCollection,
|
||||||
|
* but it is fine for OEM to re-define to their own value to adapt the legacy file reading
|
||||||
|
* logic.
|
||||||
|
*/
|
||||||
|
private static final int FILE_MAGIC = 0x414E4554;
|
||||||
|
/** Default buffer size from BufferedInputStream */
|
||||||
|
private static final int BUFFER_SIZE = 8192;
|
||||||
|
|
||||||
|
// Constructing this object is not allowed.
|
||||||
|
private NetworkStatsDataMigrationUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to read files at /data/system/netstats_*.bin.
|
||||||
|
@NonNull
|
||||||
|
private static File getPlatformSystemDir() {
|
||||||
|
return new File(Environment.getDataDirectory(), "system");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to read files at /data/system/netstats/<tag>.<start>-<end>.
|
||||||
|
@NonNull
|
||||||
|
private static File getPlatformBaseDir() {
|
||||||
|
File baseDir = new File(getPlatformSystemDir(), "netstats");
|
||||||
|
baseDir.mkdirs();
|
||||||
|
return baseDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get /data/system/netstats_*.bin legacy files. Does not check for existence.
|
||||||
|
@NonNull
|
||||||
|
private static File getLegacyBinFileForPrefix(@NonNull String prefix) {
|
||||||
|
return new File(getPlatformSystemDir(), sPrefixLegacyFileNameMap.get(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
// List /data/system/netstats/[xt|uid|uid_tag].<start>-<end> legacy files.
|
||||||
|
@NonNull
|
||||||
|
private static ArrayList<File> getPlatformFileListForPrefix(@NonNull String prefix) {
|
||||||
|
final ArrayList<File> list = new ArrayList<>();
|
||||||
|
final File platformFiles = new File(getPlatformBaseDir(), "netstats");
|
||||||
|
if (platformFiles.exists()) {
|
||||||
|
for (String name : platformFiles.list()) {
|
||||||
|
// Skip when prefix doesn't match.
|
||||||
|
if (!name.startsWith(prefix + ".")) continue;
|
||||||
|
|
||||||
|
list.add(new File(platformFiles, name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read legacy persisted network stats from disk. This function provides a default
|
||||||
|
* implementation to read persisted network stats from two different locations.
|
||||||
|
* And this is intended to be modified by OEM to read from custom file format or
|
||||||
|
* locations if necessary.
|
||||||
|
*
|
||||||
|
* @param prefix Type of data which is being read by the service.
|
||||||
|
* @param bucketDuration Duration of the buckets of the object, in milliseconds.
|
||||||
|
* @return {@link NetworkStatsCollection} instance.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static NetworkStatsCollection readPlatformCollectionLocked(
|
||||||
|
@NonNull String prefix, long bucketDuration) throws IOException {
|
||||||
|
final NetworkStatsCollection.Builder builder =
|
||||||
|
new NetworkStatsCollection.Builder(bucketDuration);
|
||||||
|
|
||||||
|
// Import /data/system/netstats_uid.bin legacy files if exists.
|
||||||
|
switch (prefix) {
|
||||||
|
case PREFIX_UID:
|
||||||
|
case PREFIX_UID_TAG:
|
||||||
|
final File uidFile = getLegacyBinFileForPrefix(prefix);
|
||||||
|
if (uidFile.exists()) {
|
||||||
|
readLegacyUid(builder, uidFile, PREFIX_UID_TAG.equals(prefix) ? true : false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Ignore other types.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import /data/system/netstats/[xt|uid|uid_tag].<start>-<end> legacy files if exists.
|
||||||
|
final ArrayList<File> platformFiles = getPlatformFileListForPrefix(prefix);
|
||||||
|
for (final File platformFile : platformFiles) {
|
||||||
|
if (platformFile.exists()) {
|
||||||
|
readPlatformCollection(builder, platformFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void readPlatformCollection(@NonNull NetworkStatsCollection.Builder builder,
|
||||||
|
@NonNull File file) throws IOException {
|
||||||
|
final FileInputStream is = new FileInputStream(file);
|
||||||
|
final FastDataInput dataIn = new FastDataInput(is, BUFFER_SIZE);
|
||||||
|
try {
|
||||||
|
readPlatformCollection(builder, dataIn);
|
||||||
|
} finally {
|
||||||
|
IoUtils.closeQuietly(dataIn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to read old version of NetworkStatsCollections that resided in the platform.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static void readPlatformCollection(@NonNull NetworkStatsCollection.Builder builder,
|
||||||
|
@NonNull DataInput in) throws IOException {
|
||||||
|
// verify file magic header intact
|
||||||
|
final int magic = in.readInt();
|
||||||
|
if (magic != FILE_MAGIC) {
|
||||||
|
throw new ProtocolException("unexpected magic: " + magic);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int version = in.readInt();
|
||||||
|
switch (version) {
|
||||||
|
case CollectionVersion.VERSION_UNIFIED_INIT: {
|
||||||
|
// uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
|
||||||
|
final int identSize = in.readInt();
|
||||||
|
for (int i = 0; i < identSize; i++) {
|
||||||
|
final Set<NetworkIdentity> ident = readPlatformNetworkIdentitySet(in);
|
||||||
|
|
||||||
|
final int size = in.readInt();
|
||||||
|
for (int j = 0; j < size; j++) {
|
||||||
|
final int uid = in.readInt();
|
||||||
|
final int set = in.readInt();
|
||||||
|
final int tag = in.readInt();
|
||||||
|
|
||||||
|
final NetworkStatsCollection.Key key = new NetworkStatsCollection.Key(
|
||||||
|
ident, uid, set, tag);
|
||||||
|
final NetworkStatsHistory history = readPlatformHistory(in);
|
||||||
|
builder.addEntry(key, history);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new ProtocolException("unexpected version: " + version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copied from NetworkStatsHistory#DataStreamUtils.
|
||||||
|
private static long[] readFullLongArray(DataInput in) throws IOException {
|
||||||
|
final int size = in.readInt();
|
||||||
|
if (size < 0) throw new ProtocolException("negative array size");
|
||||||
|
final long[] values = new long[size];
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
values[i] = in.readLong();
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copied from NetworkStatsHistory#DataStreamUtils.
|
||||||
|
private static long[] readVarLongArray(@NonNull DataInput in) throws IOException {
|
||||||
|
final int size = in.readInt();
|
||||||
|
if (size == -1) return null;
|
||||||
|
if (size < 0) throw new ProtocolException("negative array size");
|
||||||
|
final long[] values = new long[size];
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
values[i] = readVarLong(in);
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read variable-length {@link Long} using protobuf-style approach.
|
||||||
|
*/
|
||||||
|
// Copied from NetworkStatsHistory#DataStreamUtils.
|
||||||
|
private static long readVarLong(DataInput in) throws IOException {
|
||||||
|
int shift = 0;
|
||||||
|
long result = 0;
|
||||||
|
while (shift < 64) {
|
||||||
|
byte b = in.readByte();
|
||||||
|
result |= (long) (b & 0x7F) << shift;
|
||||||
|
if ((b & 0x80) == 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
shift += 7;
|
||||||
|
}
|
||||||
|
throw new ProtocolException("malformed var long");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copied from NetworkIdentitySet.
|
||||||
|
private static String readOptionalString(DataInput in) throws IOException {
|
||||||
|
if (in.readByte() != 0) {
|
||||||
|
return in.readUTF();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is copied from NetworkStatsHistory#NetworkStatsHistory(DataInput in). But it is fine
|
||||||
|
* for OEM to re-write the logic to adapt the legacy file reading.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
private static NetworkStatsHistory readPlatformHistory(@NonNull DataInput in)
|
||||||
|
throws IOException {
|
||||||
|
final long bucketDuration;
|
||||||
|
final long[] bucketStart;
|
||||||
|
final long[] rxBytes;
|
||||||
|
final long[] rxPackets;
|
||||||
|
final long[] txBytes;
|
||||||
|
final long[] txPackets;
|
||||||
|
final long[] operations;
|
||||||
|
final int bucketCount;
|
||||||
|
long[] activeTime = new long[0];
|
||||||
|
|
||||||
|
final int version = in.readInt();
|
||||||
|
switch (version) {
|
||||||
|
case HistoryVersion.VERSION_INIT: {
|
||||||
|
bucketDuration = in.readLong();
|
||||||
|
bucketStart = readFullLongArray(in);
|
||||||
|
rxBytes = readFullLongArray(in);
|
||||||
|
rxPackets = new long[bucketStart.length];
|
||||||
|
txBytes = readFullLongArray(in);
|
||||||
|
txPackets = new long[bucketStart.length];
|
||||||
|
operations = new long[bucketStart.length];
|
||||||
|
bucketCount = bucketStart.length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HistoryVersion.VERSION_ADD_PACKETS:
|
||||||
|
case HistoryVersion.VERSION_ADD_ACTIVE: {
|
||||||
|
bucketDuration = in.readLong();
|
||||||
|
bucketStart = readVarLongArray(in);
|
||||||
|
activeTime = (version >= HistoryVersion.VERSION_ADD_ACTIVE)
|
||||||
|
? readVarLongArray(in)
|
||||||
|
: new long[bucketStart.length];
|
||||||
|
rxBytes = readVarLongArray(in);
|
||||||
|
rxPackets = readVarLongArray(in);
|
||||||
|
txBytes = readVarLongArray(in);
|
||||||
|
txPackets = readVarLongArray(in);
|
||||||
|
operations = readVarLongArray(in);
|
||||||
|
bucketCount = bucketStart.length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new ProtocolException("unexpected version: " + version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final NetworkStatsHistory.Builder historyBuilder =
|
||||||
|
new NetworkStatsHistory.Builder(bucketDuration, bucketCount);
|
||||||
|
for (int i = 0; i < bucketCount; i++) {
|
||||||
|
final NetworkStatsHistory.Entry entry = new NetworkStatsHistory.Entry(
|
||||||
|
bucketStart[i], activeTime[i],
|
||||||
|
rxBytes[i], rxPackets[i], txBytes[i], txPackets[i], operations[i]);
|
||||||
|
historyBuilder.addEntry(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return historyBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private static Set<NetworkIdentity> readPlatformNetworkIdentitySet(@NonNull DataInput in)
|
||||||
|
throws IOException {
|
||||||
|
final int version = in.readInt();
|
||||||
|
final int size = in.readInt();
|
||||||
|
final Set<NetworkIdentity> set = new HashSet<>();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
if (version <= IdentitySetVersion.VERSION_INIT) {
|
||||||
|
final int ignored = in.readInt();
|
||||||
|
}
|
||||||
|
final int type = in.readInt();
|
||||||
|
final int ratType = in.readInt();
|
||||||
|
final String subscriberId = readOptionalString(in);
|
||||||
|
final String networkId;
|
||||||
|
if (version >= IdentitySetVersion.VERSION_ADD_NETWORK_ID) {
|
||||||
|
networkId = readOptionalString(in);
|
||||||
|
} else {
|
||||||
|
networkId = null;
|
||||||
|
}
|
||||||
|
final boolean roaming;
|
||||||
|
if (version >= IdentitySetVersion.VERSION_ADD_ROAMING) {
|
||||||
|
roaming = in.readBoolean();
|
||||||
|
} else {
|
||||||
|
roaming = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean metered;
|
||||||
|
if (version >= IdentitySetVersion.VERSION_ADD_METERED) {
|
||||||
|
metered = in.readBoolean();
|
||||||
|
} else {
|
||||||
|
// If this is the old data and the type is mobile, treat it as metered. (Note that
|
||||||
|
// if this is a mobile network, TYPE_MOBILE is the only possible type that could be
|
||||||
|
// used.)
|
||||||
|
metered = (type == TYPE_MOBILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean defaultNetwork;
|
||||||
|
if (version >= IdentitySetVersion.VERSION_ADD_DEFAULT_NETWORK) {
|
||||||
|
defaultNetwork = in.readBoolean();
|
||||||
|
} else {
|
||||||
|
defaultNetwork = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int oemNetCapabilities;
|
||||||
|
if (version >= IdentitySetVersion.VERSION_ADD_OEM_MANAGED_NETWORK) {
|
||||||
|
oemNetCapabilities = in.readInt();
|
||||||
|
} else {
|
||||||
|
oemNetCapabilities = NetworkIdentity.OEM_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Legacy files might contain TYPE_MOBILE_* types which were deprecated in later
|
||||||
|
// releases. For backward compatibility, record them as TYPE_MOBILE instead.
|
||||||
|
final int collapsedLegacyType = getCollapsedLegacyType(type);
|
||||||
|
final NetworkIdentity.Builder builder = new NetworkIdentity.Builder()
|
||||||
|
.setType(collapsedLegacyType)
|
||||||
|
.setSubscriberId(subscriberId)
|
||||||
|
.setWifiNetworkKey(networkId)
|
||||||
|
.setRoaming(roaming).setMetered(metered)
|
||||||
|
.setDefaultNetwork(defaultNetwork)
|
||||||
|
.setOemManaged(oemNetCapabilities);
|
||||||
|
if (type == TYPE_MOBILE && ratType != NetworkTemplate.NETWORK_TYPE_ALL) {
|
||||||
|
builder.setRatType(ratType);
|
||||||
|
}
|
||||||
|
set.add(builder.build());
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getCollapsedLegacyType(int networkType) {
|
||||||
|
// The constants are referenced from ConnectivityManager#TYPE_MOBILE_*.
|
||||||
|
switch (networkType) {
|
||||||
|
case TYPE_MOBILE:
|
||||||
|
case TYPE_MOBILE_SUPL:
|
||||||
|
case TYPE_MOBILE_MMS:
|
||||||
|
case TYPE_MOBILE_DUN:
|
||||||
|
case TYPE_MOBILE_HIPRI:
|
||||||
|
case 10 /* TYPE_MOBILE_FOTA */:
|
||||||
|
case 11 /* TYPE_MOBILE_IMS */:
|
||||||
|
case 12 /* TYPE_MOBILE_CBS */:
|
||||||
|
case 14 /* TYPE_MOBILE_IA */:
|
||||||
|
case 15 /* TYPE_MOBILE_EMERGENCY */:
|
||||||
|
return TYPE_MOBILE;
|
||||||
|
}
|
||||||
|
return networkType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void readLegacyUid(@NonNull NetworkStatsCollection.Builder builder,
|
||||||
|
@NonNull File uidFile, boolean onlyTaggedData) throws IOException {
|
||||||
|
final AtomicFile inputFile = new AtomicFile(uidFile);
|
||||||
|
DataInputStream in = new DataInputStream(new BufferedInputStream(inputFile.openRead()));
|
||||||
|
try {
|
||||||
|
readLegacyUid(builder, in, onlyTaggedData);
|
||||||
|
} finally {
|
||||||
|
IoUtils.closeQuietly(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read legacy Uid statistics file format into the collection.
|
||||||
|
*
|
||||||
|
* This is copied from {@code NetworkStatsCollection#readLegacyUid}.
|
||||||
|
* See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
|
||||||
|
*
|
||||||
|
* @param taggedData whether to read tagged data. For legacy uid files, the tagged
|
||||||
|
* data was stored in the same binary file with non-tagged data.
|
||||||
|
* But in later releases, these data should be kept in different
|
||||||
|
* recorders.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static void readLegacyUid(@NonNull NetworkStatsCollection.Builder builder,
|
||||||
|
@NonNull DataInput in, boolean taggedData) throws IOException {
|
||||||
|
try {
|
||||||
|
// verify file magic header intact
|
||||||
|
final int magic = in.readInt();
|
||||||
|
if (magic != FILE_MAGIC) {
|
||||||
|
throw new ProtocolException("unexpected magic: " + magic);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int version = in.readInt();
|
||||||
|
switch (version) {
|
||||||
|
case CollectionVersion.VERSION_UID_INIT: {
|
||||||
|
// uid := size *(UID NetworkStatsHistory)
|
||||||
|
// drop this data version, since we don't have a good
|
||||||
|
// mapping into NetworkIdentitySet.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CollectionVersion.VERSION_UID_WITH_IDENT: {
|
||||||
|
// uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory))
|
||||||
|
// drop this data version, since this version only existed
|
||||||
|
// for a short time.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CollectionVersion.VERSION_UID_WITH_TAG:
|
||||||
|
case CollectionVersion.VERSION_UID_WITH_SET: {
|
||||||
|
// uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
|
||||||
|
final int identSize = in.readInt();
|
||||||
|
for (int i = 0; i < identSize; i++) {
|
||||||
|
final Set<NetworkIdentity> ident = readPlatformNetworkIdentitySet(in);
|
||||||
|
|
||||||
|
final int size = in.readInt();
|
||||||
|
for (int j = 0; j < size; j++) {
|
||||||
|
final int uid = in.readInt();
|
||||||
|
final int set = (version >= CollectionVersion.VERSION_UID_WITH_SET)
|
||||||
|
? in.readInt()
|
||||||
|
: SET_DEFAULT;
|
||||||
|
final int tag = in.readInt();
|
||||||
|
|
||||||
|
final NetworkStatsCollection.Key key = new NetworkStatsCollection.Key(
|
||||||
|
ident, uid, set, tag);
|
||||||
|
final NetworkStatsHistory history = readPlatformHistory(in);
|
||||||
|
|
||||||
|
if ((tag == TAG_NONE) != taggedData) {
|
||||||
|
builder.addEntry(key, history);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new ProtocolException("unknown version: " + version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException | ProtocolException e) {
|
||||||
|
// missing stats is okay, probably first boot
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user