Read "qtaguid" network stats, refactor templates.
Teach NMS to read qtaguid stats from kernel, but fall back to older stats when kernel doesn't support. Add "tags" to NetworkStats entries to support qtaguid. To work around double-reporting bug, subtract tagged stats from TAG_NONE entry. Flesh out stronger NetworkTemplate. All NetworkStatsService requests now require a template, and moved matching logic into template. Record UID stats keyed on complete NetworkIdentitySet definition, similar to how interface stats are stored. Since previous UID stats didn't have iface breakdown, discard during file format upgrade. Change-Id: I0447b5e7d205d73d28e71c889c568e536e91b8e4
This commit is contained in:
@@ -18,18 +18,19 @@ package android.net;
|
|||||||
|
|
||||||
import android.net.NetworkStats;
|
import android.net.NetworkStats;
|
||||||
import android.net.NetworkStatsHistory;
|
import android.net.NetworkStatsHistory;
|
||||||
|
import android.net.NetworkTemplate;
|
||||||
|
|
||||||
/** {@hide} */
|
/** {@hide} */
|
||||||
interface INetworkStatsService {
|
interface INetworkStatsService {
|
||||||
|
|
||||||
/** Return historical stats for traffic that matches template. */
|
/** Return historical stats for traffic that matches template. */
|
||||||
NetworkStatsHistory getHistoryForNetwork(int networkTemplate);
|
NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template);
|
||||||
/** Return historical stats for specific UID traffic that matches template. */
|
/** Return historical stats for specific UID traffic that matches template. */
|
||||||
NetworkStatsHistory getHistoryForUid(int uid, int networkTemplate);
|
NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid);
|
||||||
|
|
||||||
/** Return usage summary for traffic that matches template. */
|
/** Return usage summary for traffic that matches template. */
|
||||||
NetworkStats getSummaryForNetwork(long start, long end, int networkTemplate, String subscriberId);
|
NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
|
||||||
/** Return usage summary per UID for traffic that matches template. */
|
/** Return usage summary per UID for traffic that matches template. */
|
||||||
NetworkStats getSummaryForAllUid(long start, long end, int networkTemplate);
|
NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
107
core/java/android/net/NetworkIdentity.java
Normal file
107
core/java/android/net/NetworkIdentity.java
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 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;
|
||||||
|
|
||||||
|
import static android.net.ConnectivityManager.isNetworkTypeMobile;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
|
||||||
|
import com.android.internal.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Network definition that includes strong identity. Analogous to combining
|
||||||
|
* {@link NetworkInfo} and an IMSI.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class NetworkIdentity {
|
||||||
|
final int mType;
|
||||||
|
final int mSubType;
|
||||||
|
final String mSubscriberId;
|
||||||
|
|
||||||
|
public NetworkIdentity(int type, int subType, String subscriberId) {
|
||||||
|
this.mType = type;
|
||||||
|
this.mSubType = subType;
|
||||||
|
this.mSubscriberId = subscriberId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(mType, mSubType, mSubscriberId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj instanceof NetworkIdentity) {
|
||||||
|
final NetworkIdentity ident = (NetworkIdentity) obj;
|
||||||
|
return mType == ident.mType && mSubType == ident.mSubType
|
||||||
|
&& Objects.equal(mSubscriberId, ident.mSubscriberId);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
final String typeName = ConnectivityManager.getNetworkTypeName(mType);
|
||||||
|
final String subTypeName;
|
||||||
|
if (ConnectivityManager.isNetworkTypeMobile(mType)) {
|
||||||
|
subTypeName = TelephonyManager.getNetworkTypeName(mSubType);
|
||||||
|
} else {
|
||||||
|
subTypeName = Integer.toString(mSubType);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String scrubSubscriberId = mSubscriberId != null ? "valid" : "null";
|
||||||
|
return "[type=" + typeName + ", subType=" + subTypeName + ", subscriberId="
|
||||||
|
+ scrubSubscriberId + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
return mType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSubType() {
|
||||||
|
return mSubType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubscriberId() {
|
||||||
|
return mSubscriberId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a {@link NetworkIdentity} from the given {@link NetworkState},
|
||||||
|
* assuming that any mobile networks are using the current IMSI.
|
||||||
|
*/
|
||||||
|
public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state) {
|
||||||
|
final int type = state.networkInfo.getType();
|
||||||
|
final int subType = state.networkInfo.getSubtype();
|
||||||
|
|
||||||
|
// TODO: consider moving subscriberId over to LinkCapabilities, so it
|
||||||
|
// comes from an authoritative source.
|
||||||
|
|
||||||
|
final String subscriberId;
|
||||||
|
if (isNetworkTypeMobile(type)) {
|
||||||
|
final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
|
||||||
|
Context.TELEPHONY_SERVICE);
|
||||||
|
subscriberId = telephony.getSubscriberId();
|
||||||
|
} else {
|
||||||
|
subscriberId = null;
|
||||||
|
}
|
||||||
|
return new NetworkIdentity(type, subType, subscriberId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -40,9 +40,8 @@ public class NetworkStats implements Parcelable {
|
|||||||
public static final String IFACE_ALL = null;
|
public static final String IFACE_ALL = null;
|
||||||
/** {@link #uid} value when UID details unavailable. */
|
/** {@link #uid} value when UID details unavailable. */
|
||||||
public static final int UID_ALL = -1;
|
public static final int UID_ALL = -1;
|
||||||
|
/** {@link #tag} value for without tag. */
|
||||||
// NOTE: data should only be accounted for once in this structure; if data
|
public static final int TAG_NONE = 0;
|
||||||
// is broken out, the summarized version should not be included.
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link SystemClock#elapsedRealtime()} timestamp when this data was
|
* {@link SystemClock#elapsedRealtime()} timestamp when this data was
|
||||||
@@ -52,16 +51,16 @@ public class NetworkStats implements Parcelable {
|
|||||||
public int size;
|
public int size;
|
||||||
public String[] iface;
|
public String[] iface;
|
||||||
public int[] uid;
|
public int[] uid;
|
||||||
|
public int[] tag;
|
||||||
public long[] rx;
|
public long[] rx;
|
||||||
public long[] tx;
|
public long[] tx;
|
||||||
|
|
||||||
// TODO: add fg/bg stats once reported by kernel
|
|
||||||
|
|
||||||
public NetworkStats(long elapsedRealtime, int initialSize) {
|
public NetworkStats(long elapsedRealtime, int initialSize) {
|
||||||
this.elapsedRealtime = elapsedRealtime;
|
this.elapsedRealtime = elapsedRealtime;
|
||||||
this.size = 0;
|
this.size = 0;
|
||||||
this.iface = new String[initialSize];
|
this.iface = new String[initialSize];
|
||||||
this.uid = new int[initialSize];
|
this.uid = new int[initialSize];
|
||||||
|
this.tag = new int[initialSize];
|
||||||
this.rx = new long[initialSize];
|
this.rx = new long[initialSize];
|
||||||
this.tx = new long[initialSize];
|
this.tx = new long[initialSize];
|
||||||
}
|
}
|
||||||
@@ -71,21 +70,27 @@ public class NetworkStats implements Parcelable {
|
|||||||
size = parcel.readInt();
|
size = parcel.readInt();
|
||||||
iface = parcel.createStringArray();
|
iface = parcel.createStringArray();
|
||||||
uid = parcel.createIntArray();
|
uid = parcel.createIntArray();
|
||||||
|
tag = parcel.createIntArray();
|
||||||
rx = parcel.createLongArray();
|
rx = parcel.createLongArray();
|
||||||
tx = parcel.createLongArray();
|
tx = parcel.createLongArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public NetworkStats addEntry(String iface, int uid, long rx, long tx) {
|
/**
|
||||||
|
* Add new stats entry with given values.
|
||||||
|
*/
|
||||||
|
public NetworkStats addEntry(String iface, int uid, int tag, long rx, long tx) {
|
||||||
if (size >= this.iface.length) {
|
if (size >= this.iface.length) {
|
||||||
final int newLength = Math.max(this.iface.length, 10) * 3 / 2;
|
final int newLength = Math.max(this.iface.length, 10) * 3 / 2;
|
||||||
this.iface = Arrays.copyOf(this.iface, newLength);
|
this.iface = Arrays.copyOf(this.iface, newLength);
|
||||||
this.uid = Arrays.copyOf(this.uid, newLength);
|
this.uid = Arrays.copyOf(this.uid, newLength);
|
||||||
|
this.tag = Arrays.copyOf(this.tag, newLength);
|
||||||
this.rx = Arrays.copyOf(this.rx, newLength);
|
this.rx = Arrays.copyOf(this.rx, newLength);
|
||||||
this.tx = Arrays.copyOf(this.tx, newLength);
|
this.tx = Arrays.copyOf(this.tx, newLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.iface[size] = iface;
|
this.iface[size] = iface;
|
||||||
this.uid[size] = uid;
|
this.uid[size] = uid;
|
||||||
|
this.tag[size] = tag;
|
||||||
this.rx[size] = rx;
|
this.rx[size] = rx;
|
||||||
this.tx[size] = tx;
|
this.tx[size] = tx;
|
||||||
size++;
|
size++;
|
||||||
@@ -93,17 +98,29 @@ public class NetworkStats implements Parcelable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
/**
|
||||||
public int length() {
|
* Combine given values with an existing row, or create a new row if
|
||||||
return size;
|
* {@link #findIndex(String, int, int)} is unable to find match. Can also be
|
||||||
|
* used to subtract values from existing rows.
|
||||||
|
*/
|
||||||
|
public NetworkStats combineEntry(String iface, int uid, int tag, long rx, long tx) {
|
||||||
|
final int i = findIndex(iface, uid, tag);
|
||||||
|
if (i == -1) {
|
||||||
|
// only create new entry when positive contribution
|
||||||
|
addEntry(iface, uid, tag, rx, tx);
|
||||||
|
} else {
|
||||||
|
this.rx[i] += rx;
|
||||||
|
this.tx[i] += tx;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find first stats index that matches the requested parameters.
|
* Find first stats index that matches the requested parameters.
|
||||||
*/
|
*/
|
||||||
public int findIndex(String iface, int uid) {
|
public int findIndex(String iface, int uid, int tag) {
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
if (equal(iface, this.iface[i]) && uid == this.uid[i]) {
|
if (equal(iface, this.iface[i]) && uid == this.uid[i] && tag == this.tag[i]) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,12 +203,13 @@ public class NetworkStats implements Parcelable {
|
|||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
final String iface = this.iface[i];
|
final String iface = this.iface[i];
|
||||||
final int uid = this.uid[i];
|
final int uid = this.uid[i];
|
||||||
|
final int tag = this.tag[i];
|
||||||
|
|
||||||
// find remote row that matches, and subtract
|
// find remote row that matches, and subtract
|
||||||
final int j = value.findIndex(iface, uid);
|
final int j = value.findIndex(iface, uid, tag);
|
||||||
if (j == -1) {
|
if (j == -1) {
|
||||||
// newly appearing row, return entire value
|
// newly appearing row, return entire value
|
||||||
result.addEntry(iface, uid, this.rx[i], this.tx[i]);
|
result.addEntry(iface, uid, tag, this.rx[i], this.tx[i]);
|
||||||
} else {
|
} else {
|
||||||
// existing row, subtract remote value
|
// existing row, subtract remote value
|
||||||
long rx = this.rx[i] - value.rx[j];
|
long rx = this.rx[i] - value.rx[j];
|
||||||
@@ -203,7 +221,7 @@ public class NetworkStats implements Parcelable {
|
|||||||
rx = Math.max(0, rx);
|
rx = Math.max(0, rx);
|
||||||
tx = Math.max(0, tx);
|
tx = Math.max(0, tx);
|
||||||
}
|
}
|
||||||
result.addEntry(iface, uid, rx, tx);
|
result.addEntry(iface, uid, tag, rx, tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +239,7 @@ public class NetworkStats implements Parcelable {
|
|||||||
pw.print(prefix);
|
pw.print(prefix);
|
||||||
pw.print(" iface="); pw.print(iface[i]);
|
pw.print(" iface="); pw.print(iface[i]);
|
||||||
pw.print(" uid="); pw.print(uid[i]);
|
pw.print(" uid="); pw.print(uid[i]);
|
||||||
|
pw.print(" tag="); pw.print(tag[i]);
|
||||||
pw.print(" rx="); pw.print(rx[i]);
|
pw.print(" rx="); pw.print(rx[i]);
|
||||||
pw.print(" tx="); pw.println(tx[i]);
|
pw.print(" tx="); pw.println(tx[i]);
|
||||||
}
|
}
|
||||||
@@ -244,6 +263,7 @@ public class NetworkStats implements Parcelable {
|
|||||||
dest.writeInt(size);
|
dest.writeInt(size);
|
||||||
dest.writeStringArray(iface);
|
dest.writeStringArray(iface);
|
||||||
dest.writeIntArray(uid);
|
dest.writeIntArray(uid);
|
||||||
|
dest.writeIntArray(tag);
|
||||||
dest.writeLongArray(rx);
|
dest.writeLongArray(rx);
|
||||||
dest.writeLongArray(tx);
|
dest.writeLongArray(tx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,10 +40,9 @@ import java.util.Random;
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class NetworkStatsHistory implements Parcelable {
|
public class NetworkStatsHistory implements Parcelable {
|
||||||
private static final int VERSION_CURRENT = 1;
|
private static final int VERSION_INIT = 1;
|
||||||
|
|
||||||
// TODO: teach about zigzag encoding to use less disk space
|
// TODO: teach about varint encoding to use less disk space
|
||||||
// TODO: teach how to convert between bucket sizes
|
|
||||||
|
|
||||||
public final long bucketDuration;
|
public final long bucketDuration;
|
||||||
|
|
||||||
@@ -83,7 +82,7 @@ public class NetworkStatsHistory implements Parcelable {
|
|||||||
public NetworkStatsHistory(DataInputStream in) throws IOException {
|
public NetworkStatsHistory(DataInputStream in) throws IOException {
|
||||||
final int version = in.readInt();
|
final int version = in.readInt();
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case VERSION_CURRENT: {
|
case VERSION_INIT: {
|
||||||
bucketDuration = in.readLong();
|
bucketDuration = in.readLong();
|
||||||
bucketStart = readLongArray(in);
|
bucketStart = readLongArray(in);
|
||||||
rx = readLongArray(in);
|
rx = readLongArray(in);
|
||||||
@@ -98,7 +97,7 @@ public class NetworkStatsHistory implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void writeToStream(DataOutputStream out) throws IOException {
|
public void writeToStream(DataOutputStream out) throws IOException {
|
||||||
out.writeInt(VERSION_CURRENT);
|
out.writeInt(VERSION_INIT);
|
||||||
out.writeLong(bucketDuration);
|
out.writeLong(bucketDuration);
|
||||||
writeLongArray(out, bucketStart, bucketCount);
|
writeLongArray(out, bucketStart, bucketCount);
|
||||||
writeLongArray(out, rx, bucketCount);
|
writeLongArray(out, rx, bucketCount);
|
||||||
@@ -115,6 +114,11 @@ public class NetworkStatsHistory implements Parcelable {
|
|||||||
* distribute across internal buckets, creating new buckets as needed.
|
* distribute across internal buckets, creating new buckets as needed.
|
||||||
*/
|
*/
|
||||||
public void recordData(long start, long end, long rx, long tx) {
|
public void recordData(long start, long end, long rx, long tx) {
|
||||||
|
if (rx < 0 || tx < 0) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"tried recording negative data: rx=" + rx + ", tx=" + tx);
|
||||||
|
}
|
||||||
|
|
||||||
// create any buckets needed by this range
|
// create any buckets needed by this range
|
||||||
ensureBuckets(start, end);
|
ensureBuckets(start, end);
|
||||||
|
|
||||||
|
|||||||
19
core/java/android/net/NetworkTemplate.aidl
Normal file
19
core/java/android/net/NetworkTemplate.aidl
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2011, 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;
|
||||||
|
|
||||||
|
parcelable NetworkTemplate;
|
||||||
217
core/java/android/net/NetworkTemplate.java
Normal file
217
core/java/android/net/NetworkTemplate.java
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 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;
|
||||||
|
|
||||||
|
import static android.net.ConnectivityManager.TYPE_WIFI;
|
||||||
|
import static android.net.ConnectivityManager.TYPE_WIMAX;
|
||||||
|
import static android.net.ConnectivityManager.isNetworkTypeMobile;
|
||||||
|
import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
|
||||||
|
import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
|
||||||
|
import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G;
|
||||||
|
import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN;
|
||||||
|
import static android.telephony.TelephonyManager.getNetworkClass;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import com.android.internal.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template definition used to generically match {@link NetworkIdentity},
|
||||||
|
* usually when collecting statistics.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class NetworkTemplate implements Parcelable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
|
||||||
|
* networks together. Only uses statistics for requested IMSI.
|
||||||
|
*/
|
||||||
|
public static final int MATCH_MOBILE_ALL = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
|
||||||
|
* networks together that roughly meet a "3G" definition, or lower. Only
|
||||||
|
* uses statistics for requested IMSI.
|
||||||
|
*/
|
||||||
|
public static final int MATCH_MOBILE_3G_LOWER = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
|
||||||
|
* networks together that meet a "4G" definition. Only uses statistics for
|
||||||
|
* requested IMSI.
|
||||||
|
*/
|
||||||
|
public static final int MATCH_MOBILE_4G = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template to combine all {@link ConnectivityManager#TYPE_WIFI} style
|
||||||
|
* networks together.
|
||||||
|
*/
|
||||||
|
public static final int MATCH_WIFI = 4;
|
||||||
|
|
||||||
|
final int mMatchRule;
|
||||||
|
final String mSubscriberId;
|
||||||
|
|
||||||
|
public NetworkTemplate(int matchRule, String subscriberId) {
|
||||||
|
this.mMatchRule = matchRule;
|
||||||
|
this.mSubscriberId = subscriberId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkTemplate(Parcel in) {
|
||||||
|
mMatchRule = in.readInt();
|
||||||
|
mSubscriberId = in.readString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeInt(mMatchRule);
|
||||||
|
dest.writeString(mSubscriberId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
final String scrubSubscriberId = mSubscriberId != null ? "valid" : "null";
|
||||||
|
return "NetworkTemplate: matchRule=" + getMatchRuleName(mMatchRule) + ", subscriberId="
|
||||||
|
+ scrubSubscriberId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(mMatchRule, mSubscriberId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj instanceof NetworkTemplate) {
|
||||||
|
final NetworkTemplate other = (NetworkTemplate) obj;
|
||||||
|
return mMatchRule == other.mMatchRule
|
||||||
|
&& Objects.equal(mSubscriberId, other.mSubscriberId);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMatchRule() {
|
||||||
|
return mMatchRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubscriberId() {
|
||||||
|
return mSubscriberId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if this network matches the given template and IMEI.
|
||||||
|
*/
|
||||||
|
public boolean matches(NetworkIdentity ident) {
|
||||||
|
switch (mMatchRule) {
|
||||||
|
case MATCH_MOBILE_ALL:
|
||||||
|
return matchesMobile(ident);
|
||||||
|
case MATCH_MOBILE_3G_LOWER:
|
||||||
|
return matchesMobile3gLower(ident);
|
||||||
|
case MATCH_MOBILE_4G:
|
||||||
|
return matchesMobile4g(ident);
|
||||||
|
case MATCH_WIFI:
|
||||||
|
return matchesWifi(ident);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("unknown network template");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if mobile network with matching IMEI. Also matches
|
||||||
|
* {@link #TYPE_WIMAX}.
|
||||||
|
*/
|
||||||
|
private boolean matchesMobile(NetworkIdentity ident) {
|
||||||
|
if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) {
|
||||||
|
return true;
|
||||||
|
} else if (ident.mType == TYPE_WIMAX) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if mobile network classified 3G or lower with matching IMEI.
|
||||||
|
*/
|
||||||
|
private boolean matchesMobile3gLower(NetworkIdentity ident) {
|
||||||
|
if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) {
|
||||||
|
switch (getNetworkClass(ident.mSubType)) {
|
||||||
|
case NETWORK_CLASS_UNKNOWN:
|
||||||
|
case NETWORK_CLASS_2_G:
|
||||||
|
case NETWORK_CLASS_3_G:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if mobile network classified 4G with matching IMEI. Also matches
|
||||||
|
* {@link #TYPE_WIMAX}.
|
||||||
|
*/
|
||||||
|
private boolean matchesMobile4g(NetworkIdentity ident) {
|
||||||
|
if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) {
|
||||||
|
switch (getNetworkClass(ident.mSubType)) {
|
||||||
|
case NETWORK_CLASS_4_G:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (ident.mType == TYPE_WIMAX) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if matches Wi-Fi network template.
|
||||||
|
*/
|
||||||
|
private boolean matchesWifi(NetworkIdentity ident) {
|
||||||
|
if (ident.mType == TYPE_WIFI) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMatchRuleName(int matchRule) {
|
||||||
|
switch (matchRule) {
|
||||||
|
case MATCH_MOBILE_3G_LOWER:
|
||||||
|
return "MOBILE_3G_LOWER";
|
||||||
|
case MATCH_MOBILE_4G:
|
||||||
|
return "MOBILE_4G";
|
||||||
|
case MATCH_MOBILE_ALL:
|
||||||
|
return "MOBILE_ALL";
|
||||||
|
case MATCH_WIFI:
|
||||||
|
return "WIFI";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
|
||||||
|
public NetworkTemplate createFromParcel(Parcel in) {
|
||||||
|
return new NetworkTemplate(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkTemplate[] newArray(int size) {
|
||||||
|
return new NetworkTemplate[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -41,40 +41,6 @@ public class TrafficStats {
|
|||||||
*/
|
*/
|
||||||
public final static int UNSUPPORTED = -1;
|
public final static int UNSUPPORTED = -1;
|
||||||
|
|
||||||
/**
|
|
||||||
* Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
|
|
||||||
* networks together. Only uses statistics for requested IMSI.
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public static final int TEMPLATE_MOBILE_ALL = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
|
|
||||||
* networks together that roughly meet a "3G" definition, or lower. Only
|
|
||||||
* uses statistics for requested IMSI.
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public static final int TEMPLATE_MOBILE_3G_LOWER = 2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
|
|
||||||
* networks together that meet a "4G" definition. Only uses statistics for
|
|
||||||
* requested IMSI.
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public static final int TEMPLATE_MOBILE_4G = 3;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Template to combine all {@link ConnectivityManager#TYPE_WIFI} style
|
|
||||||
* networks together.
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public static final int TEMPLATE_WIFI = 4;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Snapshot of {@link NetworkStats} when the currently active profiling
|
* Snapshot of {@link NetworkStats} when the currently active profiling
|
||||||
* session started, or {@code null} if no session active.
|
* session started, or {@code null} if no session active.
|
||||||
@@ -182,17 +148,6 @@ public class TrafficStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@hide} */
|
|
||||||
public static boolean isNetworkTemplateMobile(int networkTemplate) {
|
|
||||||
switch (networkTemplate) {
|
|
||||||
case TEMPLATE_MOBILE_3G_LOWER:
|
|
||||||
case TEMPLATE_MOBILE_4G:
|
|
||||||
case TEMPLATE_MOBILE_ALL:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of packets transmitted through the mobile interface.
|
* Get the total number of packets transmitted through the mobile interface.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.server.net;
|
package com.android.server.net;
|
||||||
|
|
||||||
|
import android.net.NetworkIdentity;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -28,19 +30,23 @@ import java.util.HashSet;
|
|||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class InterfaceIdentity extends HashSet<NetworkIdentity> {
|
public class NetworkIdentitySet extends HashSet<NetworkIdentity> {
|
||||||
private static final int VERSION_CURRENT = 1;
|
private static final int VERSION_INIT = 1;
|
||||||
|
|
||||||
public InterfaceIdentity() {
|
public NetworkIdentitySet() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public InterfaceIdentity(DataInputStream in) throws IOException {
|
public NetworkIdentitySet(DataInputStream in) throws IOException {
|
||||||
final int version = in.readInt();
|
final int version = in.readInt();
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case VERSION_CURRENT: {
|
case VERSION_INIT: {
|
||||||
final int size = in.readInt();
|
final int size = in.readInt();
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
add(new NetworkIdentity(in));
|
final int ignoredVersion = in.readInt();
|
||||||
|
final int type = in.readInt();
|
||||||
|
final int subType = in.readInt();
|
||||||
|
final String subscriberId = readOptionalString(in);
|
||||||
|
add(new NetworkIdentity(type, subType, subscriberId));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -51,23 +57,30 @@ public class InterfaceIdentity extends HashSet<NetworkIdentity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void writeToStream(DataOutputStream out) throws IOException {
|
public void writeToStream(DataOutputStream out) throws IOException {
|
||||||
out.writeInt(VERSION_CURRENT);
|
out.writeInt(VERSION_INIT);
|
||||||
out.writeInt(size());
|
out.writeInt(size());
|
||||||
for (NetworkIdentity ident : this) {
|
for (NetworkIdentity ident : this) {
|
||||||
ident.writeToStream(out);
|
out.writeInt(VERSION_INIT);
|
||||||
|
out.writeInt(ident.getType());
|
||||||
|
out.writeInt(ident.getSubType());
|
||||||
|
writeOptionalString(out, ident.getSubscriberId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private static void writeOptionalString(DataOutputStream out, String value) throws IOException {
|
||||||
* Test if any {@link NetworkIdentity} on this interface matches the given
|
if (value != null) {
|
||||||
* template and IMEI.
|
out.writeByte(1);
|
||||||
*/
|
out.writeUTF(value);
|
||||||
public boolean matchesTemplate(int networkTemplate, String subscriberId) {
|
} else {
|
||||||
for (NetworkIdentity ident : this) {
|
out.writeByte(0);
|
||||||
if (ident.matchesTemplate(networkTemplate, subscriberId)) {
|
}
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
private static String readOptionalString(DataInputStream in) throws IOException {
|
||||||
|
if (in.readByte() != 0) {
|
||||||
|
return in.readUTF();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,6 +22,7 @@ import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
|
|||||||
import static android.Manifest.permission.SHUTDOWN;
|
import static android.Manifest.permission.SHUTDOWN;
|
||||||
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
||||||
import static android.net.NetworkStats.IFACE_ALL;
|
import static android.net.NetworkStats.IFACE_ALL;
|
||||||
|
import static android.net.NetworkStats.TAG_NONE;
|
||||||
import static android.net.NetworkStats.UID_ALL;
|
import static android.net.NetworkStats.UID_ALL;
|
||||||
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
|
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
|
||||||
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
|
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
|
||||||
@@ -45,10 +46,12 @@ import android.content.IntentFilter;
|
|||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.net.IConnectivityManager;
|
import android.net.IConnectivityManager;
|
||||||
import android.net.INetworkStatsService;
|
import android.net.INetworkStatsService;
|
||||||
|
import android.net.NetworkIdentity;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
import android.net.NetworkState;
|
import android.net.NetworkState;
|
||||||
import android.net.NetworkStats;
|
import android.net.NetworkStats;
|
||||||
import android.net.NetworkStatsHistory;
|
import android.net.NetworkStatsHistory;
|
||||||
|
import android.net.NetworkTemplate;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
@@ -63,8 +66,8 @@ import android.util.SparseArray;
|
|||||||
import android.util.TrustedTime;
|
import android.util.TrustedTime;
|
||||||
|
|
||||||
import com.android.internal.os.AtomicFile;
|
import com.android.internal.os.AtomicFile;
|
||||||
import com.google.android.collect.Lists;
|
|
||||||
import com.google.android.collect.Maps;
|
import com.google.android.collect.Maps;
|
||||||
|
import com.google.android.collect.Sets;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
@@ -76,9 +79,9 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.net.ProtocolException;
|
import java.net.ProtocolException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import libcore.io.IoUtils;
|
import libcore.io.IoUtils;
|
||||||
|
|
||||||
@@ -93,7 +96,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
|
|
||||||
/** File header magic number: "ANET" */
|
/** File header magic number: "ANET" */
|
||||||
private static final int FILE_MAGIC = 0x414E4554;
|
private static final int FILE_MAGIC = 0x414E4554;
|
||||||
private static final int VERSION_CURRENT = 1;
|
private static final int VERSION_NETWORK_INIT = 1;
|
||||||
|
private static final int VERSION_UID_INIT = 1;
|
||||||
|
private static final int VERSION_UID_WITH_IDENT = 2;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final INetworkManagementService mNetworkManager;
|
private final INetworkManagementService mNetworkManager;
|
||||||
@@ -112,6 +117,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
private PendingIntent mPollIntent;
|
private PendingIntent mPollIntent;
|
||||||
|
|
||||||
// TODO: listen for kernel push events through netd instead of polling
|
// TODO: listen for kernel push events through netd instead of polling
|
||||||
|
// TODO: watch for UID uninstall, and transfer stats into single bucket
|
||||||
|
|
||||||
private static final long KB_IN_BYTES = 1024;
|
private static final long KB_IN_BYTES = 1024;
|
||||||
private static final long MB_IN_BYTES = 1024 * KB_IN_BYTES;
|
private static final long MB_IN_BYTES = 1024 * KB_IN_BYTES;
|
||||||
@@ -132,13 +138,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
|
|
||||||
private final Object mStatsLock = new Object();
|
private final Object mStatsLock = new Object();
|
||||||
|
|
||||||
/** Set of active ifaces during this boot. */
|
/** Set of currently active ifaces. */
|
||||||
private HashMap<String, InterfaceIdentity> mActiveIface = Maps.newHashMap();
|
private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
|
||||||
|
/** Set of historical stats for known networks. */
|
||||||
/** Set of historical stats for known ifaces. */
|
private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkStats = Maps.newHashMap();
|
||||||
private HashMap<InterfaceIdentity, NetworkStatsHistory> mNetworkStats = Maps.newHashMap();
|
|
||||||
/** Set of historical stats for known UIDs. */
|
/** Set of historical stats for known UIDs. */
|
||||||
private SparseArray<NetworkStatsHistory> mUidStats = new SparseArray<NetworkStatsHistory>();
|
private HashMap<NetworkIdentitySet, SparseArray<NetworkStatsHistory>> mUidStats =
|
||||||
|
Maps.newHashMap();
|
||||||
|
|
||||||
/** Flag if {@link #mUidStats} have been loaded from disk. */
|
/** Flag if {@link #mUidStats} have been loaded from disk. */
|
||||||
private boolean mUidStatsLoaded = false;
|
private boolean mUidStatsLoaded = false;
|
||||||
@@ -251,17 +257,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NetworkStatsHistory getHistoryForNetwork(int networkTemplate) {
|
public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template) {
|
||||||
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
|
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
|
||||||
|
|
||||||
synchronized (mStatsLock) {
|
synchronized (mStatsLock) {
|
||||||
// combine all interfaces that match template
|
// combine all interfaces that match template
|
||||||
final String subscriberId = getActiveSubscriberId();
|
|
||||||
final NetworkStatsHistory combined = new NetworkStatsHistory(
|
final NetworkStatsHistory combined = new NetworkStatsHistory(
|
||||||
mSettings.getNetworkBucketDuration(), estimateNetworkBuckets());
|
mSettings.getNetworkBucketDuration(), estimateNetworkBuckets());
|
||||||
for (InterfaceIdentity ident : mNetworkStats.keySet()) {
|
for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
|
||||||
final NetworkStatsHistory history = mNetworkStats.get(ident);
|
if (templateMatches(template, ident)) {
|
||||||
if (ident.matchesTemplate(networkTemplate, subscriberId)) {
|
final NetworkStatsHistory history = mNetworkStats.get(ident);
|
||||||
combined.recordEntireHistory(history);
|
combined.recordEntireHistory(history);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,19 +275,29 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NetworkStatsHistory getHistoryForUid(int uid, int networkTemplate) {
|
public NetworkStatsHistory getHistoryForUid(NetworkTemplate template, int uid) {
|
||||||
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
|
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
|
||||||
|
|
||||||
synchronized (mStatsLock) {
|
synchronized (mStatsLock) {
|
||||||
// TODO: combine based on template, if we store that granularity
|
|
||||||
ensureUidStatsLoadedLocked();
|
ensureUidStatsLoadedLocked();
|
||||||
return mUidStats.get(uid);
|
|
||||||
|
// combine all interfaces that match template
|
||||||
|
final NetworkStatsHistory combined = new NetworkStatsHistory(
|
||||||
|
mSettings.getUidBucketDuration(), estimateUidBuckets());
|
||||||
|
for (NetworkIdentitySet ident : mUidStats.keySet()) {
|
||||||
|
if (templateMatches(template, ident)) {
|
||||||
|
final NetworkStatsHistory history = mUidStats.get(ident).get(uid);
|
||||||
|
if (history != null) {
|
||||||
|
combined.recordEntireHistory(history);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return combined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NetworkStats getSummaryForNetwork(
|
public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) {
|
||||||
long start, long end, int networkTemplate, String subscriberId) {
|
|
||||||
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
|
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
|
||||||
|
|
||||||
synchronized (mStatsLock) {
|
synchronized (mStatsLock) {
|
||||||
@@ -291,9 +306,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
long[] networkTotal = new long[2];
|
long[] networkTotal = new long[2];
|
||||||
|
|
||||||
// combine total from all interfaces that match template
|
// combine total from all interfaces that match template
|
||||||
for (InterfaceIdentity ident : mNetworkStats.keySet()) {
|
for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
|
||||||
final NetworkStatsHistory history = mNetworkStats.get(ident);
|
if (templateMatches(template, ident)) {
|
||||||
if (ident.matchesTemplate(networkTemplate, subscriberId)) {
|
final NetworkStatsHistory history = mNetworkStats.get(ident);
|
||||||
networkTotal = history.getTotalData(start, end, networkTotal);
|
networkTotal = history.getTotalData(start, end, networkTotal);
|
||||||
rx += networkTotal[0];
|
rx += networkTotal[0];
|
||||||
tx += networkTotal[1];
|
tx += networkTotal[1];
|
||||||
@@ -301,30 +316,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final NetworkStats stats = new NetworkStats(end - start, 1);
|
final NetworkStats stats = new NetworkStats(end - start, 1);
|
||||||
stats.addEntry(IFACE_ALL, UID_ALL, rx, tx);
|
stats.addEntry(IFACE_ALL, UID_ALL, TAG_NONE, rx, tx);
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NetworkStats getSummaryForAllUid(long start, long end, int networkTemplate) {
|
public NetworkStats getSummaryForAllUid(NetworkTemplate template, long start, long end) {
|
||||||
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
|
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
|
||||||
|
|
||||||
// TODO: apply networktemplate once granular uid stats are stored.
|
|
||||||
|
|
||||||
synchronized (mStatsLock) {
|
synchronized (mStatsLock) {
|
||||||
ensureUidStatsLoadedLocked();
|
ensureUidStatsLoadedLocked();
|
||||||
|
|
||||||
final int size = mUidStats.size();
|
final NetworkStats stats = new NetworkStats(end - start, 24);
|
||||||
final NetworkStats stats = new NetworkStats(end - start, size);
|
|
||||||
|
|
||||||
long[] total = new long[2];
|
long[] total = new long[2];
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
final int uid = mUidStats.keyAt(i);
|
for (NetworkIdentitySet ident : mUidStats.keySet()) {
|
||||||
final NetworkStatsHistory history = mUidStats.valueAt(i);
|
if (templateMatches(template, ident)) {
|
||||||
total = history.getTotalData(start, end, total);
|
final SparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
|
||||||
stats.addEntry(IFACE_ALL, uid, total[0], total[1]);
|
for (int i = 0; i < uidStats.size(); i++) {
|
||||||
|
final int uid = uidStats.keyAt(i);
|
||||||
|
final NetworkStatsHistory history = uidStats.valueAt(i);
|
||||||
|
total = history.getTotalData(start, end, total);
|
||||||
|
stats.combineEntry(IFACE_ALL, uid, TAG_NONE, total[0], total[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -352,7 +370,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
// permission above.
|
// permission above.
|
||||||
synchronized (mStatsLock) {
|
synchronized (mStatsLock) {
|
||||||
// TODO: acquire wakelock while performing poll
|
// TODO: acquire wakelock while performing poll
|
||||||
performPollLocked(true);
|
performPollLocked(true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -371,7 +389,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
* Inspect all current {@link NetworkState} to derive mapping from {@code
|
* Inspect all current {@link NetworkState} to derive mapping from {@code
|
||||||
* iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
|
* iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
|
||||||
* are active on a single {@code iface}, they are combined under a single
|
* are active on a single {@code iface}, they are combined under a single
|
||||||
* {@link InterfaceIdentity}.
|
* {@link NetworkIdentitySet}.
|
||||||
*/
|
*/
|
||||||
private void updateIfacesLocked() {
|
private void updateIfacesLocked() {
|
||||||
if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
|
if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
|
||||||
@@ -379,7 +397,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
// take one last stats snapshot before updating iface mapping. this
|
// take one last stats snapshot before updating iface mapping. this
|
||||||
// isn't perfect, since the kernel may already be counting traffic from
|
// isn't perfect, since the kernel may already be counting traffic from
|
||||||
// the updated network.
|
// the updated network.
|
||||||
performPollLocked(false);
|
performPollLocked(false, false);
|
||||||
|
|
||||||
final NetworkState[] states;
|
final NetworkState[] states;
|
||||||
try {
|
try {
|
||||||
@@ -390,13 +408,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rebuild active interfaces based on connected networks
|
// rebuild active interfaces based on connected networks
|
||||||
mActiveIface.clear();
|
mActiveIfaces.clear();
|
||||||
|
|
||||||
for (NetworkState state : states) {
|
for (NetworkState state : states) {
|
||||||
if (state.networkInfo.isConnected()) {
|
if (state.networkInfo.isConnected()) {
|
||||||
// collect networks under their parent interfaces
|
// collect networks under their parent interfaces
|
||||||
final String iface = state.linkProperties.getInterfaceName();
|
final String iface = state.linkProperties.getInterfaceName();
|
||||||
final InterfaceIdentity ident = findOrCreateInterfaceLocked(iface);
|
|
||||||
|
NetworkIdentitySet ident = mActiveIfaces.get(iface);
|
||||||
|
if (ident == null) {
|
||||||
|
ident = new NetworkIdentitySet();
|
||||||
|
mActiveIfaces.put(iface, ident);
|
||||||
|
}
|
||||||
|
|
||||||
ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
|
ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -409,7 +433,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
* @param detailedPoll Indicate if detailed UID stats should be collected
|
* @param detailedPoll Indicate if detailed UID stats should be collected
|
||||||
* during this poll operation.
|
* during this poll operation.
|
||||||
*/
|
*/
|
||||||
private void performPollLocked(boolean detailedPoll) {
|
private void performPollLocked(boolean detailedPoll, boolean forcePersist) {
|
||||||
if (LOGV) Slog.v(TAG, "performPollLocked()");
|
if (LOGV) Slog.v(TAG, "performPollLocked()");
|
||||||
|
|
||||||
// try refreshing time source when stale
|
// try refreshing time source when stale
|
||||||
@@ -421,33 +445,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
|
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
|
||||||
: System.currentTimeMillis();
|
: System.currentTimeMillis();
|
||||||
|
|
||||||
final NetworkStats networkStats;
|
final NetworkStats ifaceStats;
|
||||||
final NetworkStats uidStats;
|
final NetworkStats uidStats;
|
||||||
try {
|
try {
|
||||||
networkStats = mNetworkManager.getNetworkStatsSummary();
|
ifaceStats = mNetworkManager.getNetworkStatsSummary();
|
||||||
uidStats = detailedPoll ? mNetworkManager.getNetworkStatsDetail() : null;
|
uidStats = detailedPoll ? mNetworkManager.getNetworkStatsDetail() : null;
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Slog.w(TAG, "problem reading network stats");
|
Slog.w(TAG, "problem reading network stats");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
performNetworkPollLocked(networkStats, currentTime);
|
performNetworkPollLocked(ifaceStats, currentTime);
|
||||||
if (detailedPoll) {
|
if (detailedPoll) {
|
||||||
performUidPollLocked(uidStats, currentTime);
|
performUidPollLocked(uidStats, currentTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// decide if enough has changed to trigger persist
|
// decide if enough has changed to trigger persist
|
||||||
final NetworkStats persistDelta = computeStatsDelta(mLastNetworkPersist, networkStats);
|
final NetworkStats persistDelta = computeStatsDelta(mLastNetworkPersist, ifaceStats);
|
||||||
final long persistThreshold = mSettings.getPersistThreshold();
|
final long persistThreshold = mSettings.getPersistThreshold();
|
||||||
for (String iface : persistDelta.getUniqueIfaces()) {
|
for (String iface : persistDelta.getUniqueIfaces()) {
|
||||||
final int index = persistDelta.findIndex(iface, UID_ALL);
|
final int index = persistDelta.findIndex(iface, UID_ALL, TAG_NONE);
|
||||||
if (persistDelta.rx[index] > persistThreshold
|
if (forcePersist || persistDelta.rx[index] > persistThreshold
|
||||||
|| persistDelta.tx[index] > persistThreshold) {
|
|| persistDelta.tx[index] > persistThreshold) {
|
||||||
writeNetworkStatsLocked();
|
writeNetworkStatsLocked();
|
||||||
if (mUidStatsLoaded) {
|
if (mUidStatsLoaded) {
|
||||||
writeUidStatsLocked();
|
writeUidStatsLocked();
|
||||||
}
|
}
|
||||||
mLastNetworkPersist = networkStats;
|
mLastNetworkPersist = ifaceStats;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -462,23 +486,23 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
* Update {@link #mNetworkStats} historical usage.
|
* Update {@link #mNetworkStats} historical usage.
|
||||||
*/
|
*/
|
||||||
private void performNetworkPollLocked(NetworkStats networkStats, long currentTime) {
|
private void performNetworkPollLocked(NetworkStats networkStats, long currentTime) {
|
||||||
final ArrayList<String> unknownIface = Lists.newArrayList();
|
final HashSet<String> unknownIface = Sets.newHashSet();
|
||||||
|
|
||||||
final NetworkStats delta = computeStatsDelta(mLastNetworkPoll, networkStats);
|
final NetworkStats delta = computeStatsDelta(mLastNetworkPoll, networkStats);
|
||||||
final long timeStart = currentTime - delta.elapsedRealtime;
|
final long timeStart = currentTime - delta.elapsedRealtime;
|
||||||
final long maxHistory = mSettings.getNetworkMaxHistory();
|
final long maxHistory = mSettings.getNetworkMaxHistory();
|
||||||
for (String iface : delta.getUniqueIfaces()) {
|
for (int i = 0; i < delta.size; i++) {
|
||||||
final InterfaceIdentity ident = mActiveIface.get(iface);
|
final String iface = delta.iface[i];
|
||||||
|
final NetworkIdentitySet ident = mActiveIfaces.get(iface);
|
||||||
if (ident == null) {
|
if (ident == null) {
|
||||||
unknownIface.add(iface);
|
unknownIface.add(iface);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int index = delta.findIndex(iface, UID_ALL);
|
final long rx = delta.rx[i];
|
||||||
final long rx = delta.rx[index];
|
final long tx = delta.tx[i];
|
||||||
final long tx = delta.tx[index];
|
|
||||||
|
|
||||||
final NetworkStatsHistory history = findOrCreateNetworkLocked(ident);
|
final NetworkStatsHistory history = findOrCreateNetworkStatsLocked(ident);
|
||||||
history.recordData(timeStart, currentTime, rx, tx);
|
history.recordData(timeStart, currentTime, rx, tx);
|
||||||
history.removeBucketsBefore(currentTime - maxHistory);
|
history.removeBucketsBefore(currentTime - maxHistory);
|
||||||
}
|
}
|
||||||
@@ -498,22 +522,30 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
final NetworkStats delta = computeStatsDelta(mLastUidPoll, uidStats);
|
final NetworkStats delta = computeStatsDelta(mLastUidPoll, uidStats);
|
||||||
final long timeStart = currentTime - delta.elapsedRealtime;
|
final long timeStart = currentTime - delta.elapsedRealtime;
|
||||||
final long maxHistory = mSettings.getUidMaxHistory();
|
final long maxHistory = mSettings.getUidMaxHistory();
|
||||||
for (int uid : delta.getUniqueUids()) {
|
|
||||||
// TODO: traverse all ifaces once surfaced in stats
|
|
||||||
final int index = delta.findIndex(IFACE_ALL, uid);
|
|
||||||
if (index != -1) {
|
|
||||||
final long rx = delta.rx[index];
|
|
||||||
final long tx = delta.tx[index];
|
|
||||||
|
|
||||||
final NetworkStatsHistory history = findOrCreateUidLocked(uid);
|
// NOTE: historical UID stats ignore tags, and simply records all stats
|
||||||
history.recordData(timeStart, currentTime, rx, tx);
|
// entries into a single UID bucket.
|
||||||
history.removeBucketsBefore(currentTime - maxHistory);
|
|
||||||
|
for (int i = 0; i < delta.size; i++) {
|
||||||
|
final String iface = delta.iface[i];
|
||||||
|
final NetworkIdentitySet ident = mActiveIfaces.get(iface);
|
||||||
|
if (ident == null) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final int uid = delta.uid[i];
|
||||||
|
final long rx = delta.rx[i];
|
||||||
|
final long tx = delta.tx[i];
|
||||||
|
|
||||||
|
final NetworkStatsHistory history = findOrCreateUidStatsLocked(ident, uid);
|
||||||
|
history.recordData(timeStart, currentTime, rx, tx);
|
||||||
|
history.removeBucketsBefore(currentTime - maxHistory);
|
||||||
}
|
}
|
||||||
|
|
||||||
mLastUidPoll = uidStats;
|
mLastUidPoll = uidStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
private NetworkStatsHistory findOrCreateNetworkLocked(InterfaceIdentity ident) {
|
private NetworkStatsHistory findOrCreateNetworkStatsLocked(NetworkIdentitySet ident) {
|
||||||
final long bucketDuration = mSettings.getNetworkBucketDuration();
|
final long bucketDuration = mSettings.getNetworkBucketDuration();
|
||||||
final NetworkStatsHistory existing = mNetworkStats.get(ident);
|
final NetworkStatsHistory existing = mNetworkStats.get(ident);
|
||||||
|
|
||||||
@@ -535,9 +567,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private NetworkStatsHistory findOrCreateUidLocked(int uid) {
|
private NetworkStatsHistory findOrCreateUidStatsLocked(NetworkIdentitySet ident, int uid) {
|
||||||
|
// find bucket for identity first, then find uid
|
||||||
|
SparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
|
||||||
|
if (uidStats == null) {
|
||||||
|
uidStats = new SparseArray<NetworkStatsHistory>();
|
||||||
|
mUidStats.put(ident, uidStats);
|
||||||
|
}
|
||||||
|
|
||||||
final long bucketDuration = mSettings.getUidBucketDuration();
|
final long bucketDuration = mSettings.getUidBucketDuration();
|
||||||
final NetworkStatsHistory existing = mUidStats.get(uid);
|
final NetworkStatsHistory existing = uidStats.get(uid);
|
||||||
|
|
||||||
// update when no existing, or when bucket duration changed
|
// update when no existing, or when bucket duration changed
|
||||||
NetworkStatsHistory updated = null;
|
NetworkStatsHistory updated = null;
|
||||||
@@ -550,22 +589,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (updated != null) {
|
if (updated != null) {
|
||||||
mUidStats.put(uid, updated);
|
uidStats.put(uid, updated);
|
||||||
return updated;
|
return updated;
|
||||||
} else {
|
} else {
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private InterfaceIdentity findOrCreateInterfaceLocked(String iface) {
|
|
||||||
InterfaceIdentity ident = mActiveIface.get(iface);
|
|
||||||
if (ident == null) {
|
|
||||||
ident = new InterfaceIdentity();
|
|
||||||
mActiveIface.put(iface, ident);
|
|
||||||
}
|
|
||||||
return ident;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readNetworkStatsLocked() {
|
private void readNetworkStatsLocked() {
|
||||||
if (LOGV) Slog.v(TAG, "readNetworkStatsLocked()");
|
if (LOGV) Slog.v(TAG, "readNetworkStatsLocked()");
|
||||||
|
|
||||||
@@ -585,15 +615,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
|
|
||||||
final int version = in.readInt();
|
final int version = in.readInt();
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case VERSION_CURRENT: {
|
case VERSION_NETWORK_INIT: {
|
||||||
// file format is pairs of interfaces and stats:
|
// network := size *(NetworkIdentitySet NetworkStatsHistory)
|
||||||
// network := size *(InterfaceIdentity NetworkStatsHistory)
|
|
||||||
|
|
||||||
final int size = in.readInt();
|
final int size = in.readInt();
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
final InterfaceIdentity ident = new InterfaceIdentity(in);
|
final NetworkIdentitySet ident = new NetworkIdentitySet(in);
|
||||||
final NetworkStatsHistory history = new NetworkStatsHistory(in);
|
final NetworkStatsHistory history = new NetworkStatsHistory(in);
|
||||||
|
|
||||||
mNetworkStats.put(ident, history);
|
mNetworkStats.put(ident, history);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -637,16 +664,29 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
|
|
||||||
final int version = in.readInt();
|
final int version = in.readInt();
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case VERSION_CURRENT: {
|
case VERSION_UID_INIT: {
|
||||||
// file format is pairs of UIDs and stats:
|
|
||||||
// uid := size *(UID NetworkStatsHistory)
|
// uid := size *(UID NetworkStatsHistory)
|
||||||
|
|
||||||
final int size = in.readInt();
|
// drop this data version, since we don't have a good
|
||||||
for (int i = 0; i < size; i++) {
|
// mapping into NetworkIdentitySet.
|
||||||
final int uid = in.readInt();
|
break;
|
||||||
final NetworkStatsHistory history = new NetworkStatsHistory(in);
|
}
|
||||||
|
case VERSION_UID_WITH_IDENT: {
|
||||||
|
// uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory))
|
||||||
|
final int ifaceSize = in.readInt();
|
||||||
|
for (int i = 0; i < ifaceSize; i++) {
|
||||||
|
final NetworkIdentitySet ident = new NetworkIdentitySet(in);
|
||||||
|
|
||||||
mUidStats.put(uid, history);
|
final int uidSize = in.readInt();
|
||||||
|
final SparseArray<NetworkStatsHistory> uidStats = new SparseArray<
|
||||||
|
NetworkStatsHistory>(uidSize);
|
||||||
|
for (int j = 0; j < uidSize; j++) {
|
||||||
|
final int uid = in.readInt();
|
||||||
|
final NetworkStatsHistory history = new NetworkStatsHistory(in);
|
||||||
|
uidStats.put(uid, history);
|
||||||
|
}
|
||||||
|
|
||||||
|
mUidStats.put(ident, uidStats);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -674,10 +714,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
final DataOutputStream out = new DataOutputStream(fos);
|
final DataOutputStream out = new DataOutputStream(fos);
|
||||||
|
|
||||||
out.writeInt(FILE_MAGIC);
|
out.writeInt(FILE_MAGIC);
|
||||||
out.writeInt(VERSION_CURRENT);
|
out.writeInt(VERSION_NETWORK_INIT);
|
||||||
|
|
||||||
out.writeInt(mNetworkStats.size());
|
out.writeInt(mNetworkStats.size());
|
||||||
for (InterfaceIdentity ident : mNetworkStats.keySet()) {
|
for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
|
||||||
final NetworkStatsHistory history = mNetworkStats.get(ident);
|
final NetworkStatsHistory history = mNetworkStats.get(ident);
|
||||||
ident.writeToStream(out);
|
ident.writeToStream(out);
|
||||||
history.writeToStream(out);
|
history.writeToStream(out);
|
||||||
@@ -702,16 +742,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
final DataOutputStream out = new DataOutputStream(fos);
|
final DataOutputStream out = new DataOutputStream(fos);
|
||||||
|
|
||||||
out.writeInt(FILE_MAGIC);
|
out.writeInt(FILE_MAGIC);
|
||||||
out.writeInt(VERSION_CURRENT);
|
out.writeInt(VERSION_UID_WITH_IDENT);
|
||||||
|
|
||||||
final int size = mUidStats.size();
|
out.writeInt(mUidStats.size());
|
||||||
|
for (NetworkIdentitySet ident : mUidStats.keySet()) {
|
||||||
|
final SparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
|
||||||
|
ident.writeToStream(out);
|
||||||
|
|
||||||
out.writeInt(size);
|
final int size = uidStats.size();
|
||||||
for (int i = 0; i < size; i++) {
|
out.writeInt(size);
|
||||||
final int uid = mUidStats.keyAt(i);
|
for (int i = 0; i < size; i++) {
|
||||||
final NetworkStatsHistory history = mUidStats.valueAt(i);
|
final int uid = uidStats.keyAt(i);
|
||||||
out.writeInt(uid);
|
final NetworkStatsHistory history = uidStats.valueAt(i);
|
||||||
history.writeToStream(out);
|
out.writeInt(uid);
|
||||||
|
history.writeToStream(out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mUidFile.finishWrite(fos);
|
mUidFile.finishWrite(fos);
|
||||||
@@ -740,35 +785,41 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (argSet.contains("poll")) {
|
if (argSet.contains("poll")) {
|
||||||
performPollLocked(true);
|
performPollLocked(true, true);
|
||||||
pw.println("Forced poll");
|
pw.println("Forced poll");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pw.println("Active interfaces:");
|
pw.println("Active interfaces:");
|
||||||
for (String iface : mActiveIface.keySet()) {
|
for (String iface : mActiveIfaces.keySet()) {
|
||||||
final InterfaceIdentity ident = mActiveIface.get(iface);
|
final NetworkIdentitySet ident = mActiveIfaces.get(iface);
|
||||||
pw.print(" iface="); pw.print(iface);
|
pw.print(" iface="); pw.print(iface);
|
||||||
pw.print(" ident="); pw.println(ident.toString());
|
pw.print(" ident="); pw.println(ident.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
pw.println("Known historical stats:");
|
pw.println("Known historical stats:");
|
||||||
for (InterfaceIdentity ident : mNetworkStats.keySet()) {
|
for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
|
||||||
final NetworkStatsHistory stats = mNetworkStats.get(ident);
|
final NetworkStatsHistory history = mNetworkStats.get(ident);
|
||||||
pw.print(" ident="); pw.println(ident.toString());
|
pw.print(" ident="); pw.println(ident.toString());
|
||||||
stats.dump(" ", pw);
|
history.dump(" ", pw);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argSet.contains("detail")) {
|
if (argSet.contains("detail")) {
|
||||||
// since explicitly requested with argument, we're okay to load
|
// since explicitly requested with argument, we're okay to load
|
||||||
// from disk if not already in memory.
|
// from disk if not already in memory.
|
||||||
ensureUidStatsLoadedLocked();
|
ensureUidStatsLoadedLocked();
|
||||||
pw.println("Known UID stats:");
|
|
||||||
for (int i = 0; i < mUidStats.size(); i++) {
|
pw.println("Detailed UID stats:");
|
||||||
final int uid = mUidStats.keyAt(i);
|
for (NetworkIdentitySet ident : mUidStats.keySet()) {
|
||||||
final NetworkStatsHistory stats = mUidStats.valueAt(i);
|
pw.print(" ident="); pw.println(ident.toString());
|
||||||
pw.print(" UID="); pw.println(uid);
|
|
||||||
stats.dump(" ", pw);
|
final SparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
|
||||||
|
for (int i = 0; i < uidStats.size(); i++) {
|
||||||
|
final int uid = uidStats.keyAt(i);
|
||||||
|
final NetworkStatsHistory history = uidStats.valueAt(i);
|
||||||
|
pw.print(" UID="); pw.println(uid);
|
||||||
|
history.dump(" ", pw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -779,27 +830,30 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
private void generateRandomLocked() {
|
private void generateRandomLocked() {
|
||||||
long end = System.currentTimeMillis();
|
long networkEnd = System.currentTimeMillis();
|
||||||
long start = end - mSettings.getNetworkMaxHistory();
|
long networkStart = networkEnd - mSettings.getNetworkMaxHistory();
|
||||||
long rx = 3 * GB_IN_BYTES;
|
long networkRx = 3 * GB_IN_BYTES;
|
||||||
long tx = 2 * GB_IN_BYTES;
|
long networkTx = 2 * GB_IN_BYTES;
|
||||||
|
|
||||||
|
long uidEnd = System.currentTimeMillis();
|
||||||
|
long uidStart = uidEnd - mSettings.getUidMaxHistory();
|
||||||
|
long uidRx = 500 * MB_IN_BYTES;
|
||||||
|
long uidTx = 100 * MB_IN_BYTES;
|
||||||
|
|
||||||
|
final List<ApplicationInfo> installedApps = mContext
|
||||||
|
.getPackageManager().getInstalledApplications(0);
|
||||||
|
|
||||||
mNetworkStats.clear();
|
mNetworkStats.clear();
|
||||||
for (InterfaceIdentity ident : mActiveIface.values()) {
|
|
||||||
final NetworkStatsHistory stats = findOrCreateNetworkLocked(ident);
|
|
||||||
stats.generateRandom(start, end, rx, tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
end = System.currentTimeMillis();
|
|
||||||
start = end - mSettings.getUidMaxHistory();
|
|
||||||
rx = 500 * MB_IN_BYTES;
|
|
||||||
tx = 100 * MB_IN_BYTES;
|
|
||||||
|
|
||||||
mUidStats.clear();
|
mUidStats.clear();
|
||||||
for (ApplicationInfo info : mContext.getPackageManager().getInstalledApplications(0)) {
|
for (NetworkIdentitySet ident : mActiveIfaces.values()) {
|
||||||
final int uid = info.uid;
|
findOrCreateNetworkStatsLocked(ident).generateRandom(
|
||||||
final NetworkStatsHistory stats = findOrCreateUidLocked(uid);
|
networkStart, networkEnd, networkRx, networkTx);
|
||||||
stats.generateRandom(start, end, rx, tx);
|
|
||||||
|
for (ApplicationInfo info : installedApps) {
|
||||||
|
final int uid = info.uid;
|
||||||
|
findOrCreateUidStatsLocked(ident, uid).generateRandom(
|
||||||
|
uidStart, uidEnd, uidRx, uidTx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,12 +869,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getActiveSubscriberId() {
|
|
||||||
final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService(
|
|
||||||
Context.TELEPHONY_SERVICE);
|
|
||||||
return telephony.getSubscriberId();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int estimateNetworkBuckets() {
|
private int estimateNetworkBuckets() {
|
||||||
return (int) (mSettings.getNetworkMaxHistory() / mSettings.getNetworkBucketDuration());
|
return (int) (mSettings.getNetworkMaxHistory() / mSettings.getNetworkBucketDuration());
|
||||||
}
|
}
|
||||||
@@ -833,6 +881,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
return (int) (existing.bucketCount * existing.bucketDuration / newBucketDuration);
|
return (int) (existing.bucketCount * existing.bucketDuration / newBucketDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity}
|
||||||
|
* in the given {@link NetworkIdentitySet}.
|
||||||
|
*/
|
||||||
|
private static boolean templateMatches(NetworkTemplate template, NetworkIdentitySet identSet) {
|
||||||
|
for (NetworkIdentity ident : identSet) {
|
||||||
|
if (template.matches(ident)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default external settings that read from {@link Settings.Secure}.
|
* Default external settings that read from {@link Settings.Secure}.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user