diff options
Diffstat (limited to 'core/java/android/net')
-rw-r--r-- | core/java/android/net/INetworkStatsService.aidl | 9 | ||||
-rw-r--r-- | core/java/android/net/NetworkIdentity.java | 107 | ||||
-rw-r--r-- | core/java/android/net/NetworkPolicy.java | 32 | ||||
-rw-r--r-- | core/java/android/net/NetworkPolicyManager.java | 2 | ||||
-rw-r--r-- | core/java/android/net/NetworkStats.java | 48 | ||||
-rw-r--r-- | core/java/android/net/NetworkStatsHistory.java | 14 | ||||
-rw-r--r-- | core/java/android/net/NetworkTemplate.aidl | 19 | ||||
-rw-r--r-- | core/java/android/net/NetworkTemplate.java | 217 | ||||
-rw-r--r-- | core/java/android/net/TrafficStats.java | 45 |
9 files changed, 408 insertions, 85 deletions
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 288112a..6371500 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -18,18 +18,19 @@ package android.net; import android.net.NetworkStats; import android.net.NetworkStatsHistory; +import android.net.NetworkTemplate; /** {@hide} */ interface INetworkStatsService { /** 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. */ - NetworkStatsHistory getHistoryForUid(int uid, int networkTemplate); + NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid); /** 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. */ - NetworkStats getSummaryForAllUid(long start, long end, int networkTemplate); + NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end); } diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java new file mode 100644 index 0000000..f82d922 --- /dev/null +++ b/core/java/android/net/NetworkIdentity.java @@ -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); + } + +} diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java index 1899281..52cab30 100644 --- a/core/java/android/net/NetworkPolicy.java +++ b/core/java/android/net/NetworkPolicy.java @@ -16,37 +16,38 @@ package android.net; +import static com.android.internal.util.Preconditions.checkNotNull; + import android.os.Parcel; import android.os.Parcelable; /** - * Policy for a specific network, including usage cycle and limits to be - * enforced. + * Policy for networks matching a {@link NetworkTemplate}, including usage cycle + * and limits to be enforced. * * @hide */ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> { - public final int networkTemplate; - public final String subscriberId; + public static final long WARNING_DISABLED = -1; + public static final long LIMIT_DISABLED = -1; + + public final NetworkTemplate template; public int cycleDay; public long warningBytes; public long limitBytes; - public static final long WARNING_DISABLED = -1; - public static final long LIMIT_DISABLED = -1; + // TODO: teach how to snooze limit for current cycle - public NetworkPolicy(int networkTemplate, String subscriberId, int cycleDay, long warningBytes, - long limitBytes) { - this.networkTemplate = networkTemplate; - this.subscriberId = subscriberId; + public NetworkPolicy( + NetworkTemplate template, int cycleDay, long warningBytes, long limitBytes) { + this.template = checkNotNull(template, "missing NetworkTemplate"); this.cycleDay = cycleDay; this.warningBytes = warningBytes; this.limitBytes = limitBytes; } public NetworkPolicy(Parcel in) { - networkTemplate = in.readInt(); - subscriberId = in.readString(); + template = in.readParcelable(null); cycleDay = in.readInt(); warningBytes = in.readLong(); limitBytes = in.readLong(); @@ -54,8 +55,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> { /** {@inheritDoc} */ public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(networkTemplate); - dest.writeString(subscriberId); + dest.writeParcelable(template, flags); dest.writeInt(cycleDay); dest.writeLong(warningBytes); dest.writeLong(limitBytes); @@ -81,8 +81,8 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> { @Override public String toString() { - return "NetworkPolicy: networkTemplate=" + networkTemplate + ", cycleDay=" + cycleDay - + ", warningBytes=" + warningBytes + ", limitBytes=" + limitBytes; + return "NetworkPolicy[" + template + "]: cycleDay=" + cycleDay + ", warningBytes=" + + warningBytes + ", limitBytes=" + limitBytes; } public static final Creator<NetworkPolicy> CREATOR = new Creator<NetworkPolicy>() { diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index bfea168..91af16d 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -59,7 +59,7 @@ public class NetworkPolicyManager { /** * {@link Intent} extra included in {@link #ACTION_DATA_USAGE_WARNING} and * {@link #ACTION_DATA_USAGE_LIMIT} to indicate which - * {@link NetworkPolicy#networkTemplate} it applies to. + * {@link NetworkTemplate} rule it applies to. */ public static final String EXTRA_NETWORK_TEMPLATE = "android.intent.extra.NETWORK_TEMPLATE"; diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 60f740e..9d40c42 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -40,9 +40,8 @@ public class NetworkStats implements Parcelable { public static final String IFACE_ALL = null; /** {@link #uid} value when UID details unavailable. */ public static final int UID_ALL = -1; - - // NOTE: data should only be accounted for once in this structure; if data - // is broken out, the summarized version should not be included. + /** {@link #tag} value for without tag. */ + public static final int TAG_NONE = 0; /** * {@link SystemClock#elapsedRealtime()} timestamp when this data was @@ -52,16 +51,16 @@ public class NetworkStats implements Parcelable { public int size; public String[] iface; public int[] uid; + public int[] tag; public long[] rx; public long[] tx; - // TODO: add fg/bg stats once reported by kernel - public NetworkStats(long elapsedRealtime, int initialSize) { this.elapsedRealtime = elapsedRealtime; this.size = 0; this.iface = new String[initialSize]; this.uid = new int[initialSize]; + this.tag = new int[initialSize]; this.rx = new long[initialSize]; this.tx = new long[initialSize]; } @@ -71,21 +70,27 @@ public class NetworkStats implements Parcelable { size = parcel.readInt(); iface = parcel.createStringArray(); uid = parcel.createIntArray(); + tag = parcel.createIntArray(); rx = 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) { final int newLength = Math.max(this.iface.length, 10) * 3 / 2; this.iface = Arrays.copyOf(this.iface, newLength); this.uid = Arrays.copyOf(this.uid, newLength); + this.tag = Arrays.copyOf(this.tag, newLength); this.rx = Arrays.copyOf(this.rx, newLength); this.tx = Arrays.copyOf(this.tx, newLength); } this.iface[size] = iface; this.uid[size] = uid; + this.tag[size] = tag; this.rx[size] = rx; this.tx[size] = tx; size++; @@ -93,17 +98,29 @@ public class NetworkStats implements Parcelable { return this; } - @Deprecated - public int length() { - return size; + /** + * Combine given values with an existing row, or create a new row if + * {@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. */ - public int findIndex(String iface, int uid) { + public int findIndex(String iface, int uid, int tag) { 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; } } @@ -186,12 +203,13 @@ public class NetworkStats implements Parcelable { for (int i = 0; i < size; i++) { final String iface = this.iface[i]; final int uid = this.uid[i]; + final int tag = this.tag[i]; // 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) { // 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 { // existing row, subtract remote value long rx = this.rx[i] - value.rx[j]; @@ -203,7 +221,7 @@ public class NetworkStats implements Parcelable { rx = Math.max(0, rx); 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(" iface="); pw.print(iface[i]); pw.print(" uid="); pw.print(uid[i]); + pw.print(" tag="); pw.print(tag[i]); pw.print(" rx="); pw.print(rx[i]); pw.print(" tx="); pw.println(tx[i]); } @@ -244,6 +263,7 @@ public class NetworkStats implements Parcelable { dest.writeInt(size); dest.writeStringArray(iface); dest.writeIntArray(uid); + dest.writeIntArray(tag); dest.writeLongArray(rx); dest.writeLongArray(tx); } diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 5fa8e21..ff6e220 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -40,10 +40,9 @@ import java.util.Random; * @hide */ 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 how to convert between bucket sizes + // TODO: teach about varint encoding to use less disk space public final long bucketDuration; @@ -83,7 +82,7 @@ public class NetworkStatsHistory implements Parcelable { public NetworkStatsHistory(DataInputStream in) throws IOException { final int version = in.readInt(); switch (version) { - case VERSION_CURRENT: { + case VERSION_INIT: { bucketDuration = in.readLong(); bucketStart = readLongArray(in); rx = readLongArray(in); @@ -98,7 +97,7 @@ public class NetworkStatsHistory implements Parcelable { } public void writeToStream(DataOutputStream out) throws IOException { - out.writeInt(VERSION_CURRENT); + out.writeInt(VERSION_INIT); out.writeLong(bucketDuration); writeLongArray(out, bucketStart, bucketCount); writeLongArray(out, rx, bucketCount); @@ -115,6 +114,11 @@ public class NetworkStatsHistory implements Parcelable { * distribute across internal buckets, creating new buckets as needed. */ 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 ensureBuckets(start, end); diff --git a/core/java/android/net/NetworkTemplate.aidl b/core/java/android/net/NetworkTemplate.aidl new file mode 100644 index 0000000..3d37488 --- /dev/null +++ b/core/java/android/net/NetworkTemplate.aidl @@ -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; diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java new file mode 100644 index 0000000..9381f1d --- /dev/null +++ b/core/java/android/net/NetworkTemplate.java @@ -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]; + } + }; +} diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 3725fa6..e163abf 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -42,40 +42,6 @@ public class TrafficStats { 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 * 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. * |