DO NOT MERGE - Merge pie-platform-release (PPRL.181205.001) into master
Bug: 120502534
Change-Id: Idc8bfb6d97a869b76cfb87ca1a494201baf9e8bd
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 9f46f20..59ae334 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -21,6 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
import android.app.usage.NetworkStats.Bucket;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -121,6 +122,7 @@
/**
* {@hide}
*/
+ @UnsupportedAppUsage
public NetworkStatsManager(Context context) throws ServiceNotFoundException {
this(context, INetworkStatsService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index ecccda5..7256502 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
@@ -66,6 +67,7 @@
* @param iface Ethernet interface name
* @param isAvailable {@code true} if Ethernet port exists.
*/
+ @UnsupportedAppUsage
void onAvailabilityChanged(String iface, boolean isAvailable);
}
@@ -84,6 +86,7 @@
* Get Ethernet configuration.
* @return the Ethernet Configuration, contained in {@link IpConfiguration}.
*/
+ @UnsupportedAppUsage
public IpConfiguration getConfiguration(String iface) {
try {
return mService.getConfiguration(iface);
@@ -95,6 +98,7 @@
/**
* Set Ethernet configuration.
*/
+ @UnsupportedAppUsage
public void setConfiguration(String iface, IpConfiguration config) {
try {
mService.setConfiguration(iface, config);
@@ -106,6 +110,7 @@
/**
* Indicates whether the system currently has one or more Ethernet interfaces.
*/
+ @UnsupportedAppUsage
public boolean isAvailable() {
return getAvailableInterfaces().length > 0;
}
@@ -115,6 +120,7 @@
*
* @param iface Ethernet interface name
*/
+ @UnsupportedAppUsage
public boolean isAvailable(String iface) {
try {
return mService.isAvailable(iface);
@@ -128,6 +134,7 @@
* @param listener A {@link Listener} to add.
* @throws IllegalArgumentException If the listener is null.
*/
+ @UnsupportedAppUsage
public void addListener(Listener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
@@ -145,6 +152,7 @@
/**
* Returns an array of available Ethernet interface names.
*/
+ @UnsupportedAppUsage
public String[] getAvailableInterfaces() {
try {
return mService.getAvailableInterfaces();
@@ -158,6 +166,7 @@
* @param listener A {@link Listener} to remove.
* @throws IllegalArgumentException If the listener is null.
*/
+ @UnsupportedAppUsage
public void removeListener(Listener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
index 8599f47..3552655 100644
--- a/core/java/android/net/IpSecConfig.java
+++ b/core/java/android/net/IpSecConfig.java
@@ -65,10 +65,13 @@
// An interval, in seconds between the NattKeepalive packets
private int mNattKeepaliveInterval;
- // XFRM mark and mask
+ // XFRM mark and mask; defaults to 0 (no mark/mask)
private int mMarkValue;
private int mMarkMask;
+ // XFRM interface id
+ private int mXfrmInterfaceId;
+
/** Set the mode for this IPsec transform */
public void setMode(int mode) {
mMode = mode;
@@ -125,14 +128,30 @@
mNattKeepaliveInterval = interval;
}
+ /**
+ * Sets the mark value
+ *
+ * <p>Internal (System server) use only. Marks passed in by users will be overwritten or
+ * ignored.
+ */
public void setMarkValue(int mark) {
mMarkValue = mark;
}
+ /**
+ * Sets the mark mask
+ *
+ * <p>Internal (System server) use only. Marks passed in by users will be overwritten or
+ * ignored.
+ */
public void setMarkMask(int mask) {
mMarkMask = mask;
}
+ public void setXfrmInterfaceId(int xfrmInterfaceId) {
+ mXfrmInterfaceId = xfrmInterfaceId;
+ }
+
// Transport or Tunnel
public int getMode() {
return mMode;
@@ -190,6 +209,10 @@
return mMarkMask;
}
+ public int getXfrmInterfaceId() {
+ return mXfrmInterfaceId;
+ }
+
// Parcelable Methods
@Override
@@ -213,6 +236,7 @@
out.writeInt(mNattKeepaliveInterval);
out.writeInt(mMarkValue);
out.writeInt(mMarkMask);
+ out.writeInt(mXfrmInterfaceId);
}
@VisibleForTesting
@@ -235,6 +259,7 @@
mNattKeepaliveInterval = c.mNattKeepaliveInterval;
mMarkValue = c.mMarkValue;
mMarkMask = c.mMarkMask;
+ mXfrmInterfaceId = c.mXfrmInterfaceId;
}
private IpSecConfig(Parcel in) {
@@ -255,6 +280,7 @@
mNattKeepaliveInterval = in.readInt();
mMarkValue = in.readInt();
mMarkMask = in.readInt();
+ mXfrmInterfaceId = in.readInt();
}
@Override
@@ -289,6 +315,8 @@
.append(mMarkValue)
.append(", mMarkMask=")
.append(mMarkMask)
+ .append(", mXfrmInterfaceId=")
+ .append(mXfrmInterfaceId)
.append("}");
return strBuilder.toString();
@@ -320,10 +348,10 @@
&& lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval
&& lhs.mSpiResourceId == rhs.mSpiResourceId
&& IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption)
- && IpSecAlgorithm.equals(
- lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption)
+ && IpSecAlgorithm.equals(lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption)
&& IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication)
&& lhs.mMarkValue == rhs.mMarkValue
- && lhs.mMarkMask == rhs.mMarkMask);
+ && lhs.mMarkMask == rhs.mMarkMask
+ && lhs.mXfrmInterfaceId == rhs.mXfrmInterfaceId);
}
}
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index edf9bc1..a00b9a3 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -43,6 +44,7 @@
*
* @hide
*/
+// @NotThreadSafe
public class NetworkStats implements Parcelable {
private static final String TAG = "NetworkStats";
/** {@link #iface} value when interface details unavailable. */
@@ -110,25 +112,43 @@
* generated.
*/
private long elapsedRealtime;
+ @UnsupportedAppUsage
private int size;
+ @UnsupportedAppUsage
private int capacity;
+ @UnsupportedAppUsage
private String[] iface;
+ @UnsupportedAppUsage
private int[] uid;
+ @UnsupportedAppUsage
private int[] set;
+ @UnsupportedAppUsage
private int[] tag;
+ @UnsupportedAppUsage
private int[] metered;
+ @UnsupportedAppUsage
private int[] roaming;
+ @UnsupportedAppUsage
private int[] defaultNetwork;
+ @UnsupportedAppUsage
private long[] rxBytes;
+ @UnsupportedAppUsage
private long[] rxPackets;
+ @UnsupportedAppUsage
private long[] txBytes;
+ @UnsupportedAppUsage
private long[] txPackets;
+ @UnsupportedAppUsage
private long[] operations;
public static class Entry {
+ @UnsupportedAppUsage
public String iface;
+ @UnsupportedAppUsage
public int uid;
+ @UnsupportedAppUsage
public int set;
+ @UnsupportedAppUsage
public int tag;
/**
* Note that this is only populated w/ the default value when read from /proc or written
@@ -148,12 +168,17 @@
* getSummary().
*/
public int defaultNetwork;
+ @UnsupportedAppUsage
public long rxBytes;
+ @UnsupportedAppUsage
public long rxPackets;
+ @UnsupportedAppUsage
public long txBytes;
+ @UnsupportedAppUsage
public long txPackets;
public long operations;
+ @UnsupportedAppUsage
public Entry() {
this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
}
@@ -240,6 +265,7 @@
}
}
+ @UnsupportedAppUsage
public NetworkStats(long elapsedRealtime, int initialSize) {
this.elapsedRealtime = elapsedRealtime;
this.size = 0;
@@ -263,6 +289,7 @@
}
}
+ @UnsupportedAppUsage
public NetworkStats(Parcel parcel) {
elapsedRealtime = parcel.readLong();
size = parcel.readInt();
@@ -399,6 +426,7 @@
/**
* Return specific stats entry.
*/
+ @UnsupportedAppUsage
public Entry getValues(int i, Entry recycle) {
final Entry entry = recycle != null ? recycle : new Entry();
entry.iface = iface[i];
@@ -416,6 +444,26 @@
return entry;
}
+ /**
+ * If @{code dest} is not equal to @{code src}, copy entry from index @{code src} to index
+ * @{code dest}.
+ */
+ private void maybeCopyEntry(int dest, int src) {
+ if (dest == src) return;
+ iface[dest] = iface[src];
+ uid[dest] = uid[src];
+ set[dest] = set[src];
+ tag[dest] = tag[src];
+ metered[dest] = metered[src];
+ roaming[dest] = roaming[src];
+ defaultNetwork[dest] = defaultNetwork[src];
+ rxBytes[dest] = rxBytes[src];
+ rxPackets[dest] = rxPackets[src];
+ txBytes[dest] = txBytes[src];
+ txPackets[dest] = txPackets[src];
+ operations[dest] = operations[src];
+ }
+
public long getElapsedRealtime() {
return elapsedRealtime;
}
@@ -432,6 +480,7 @@
return SystemClock.elapsedRealtime() - elapsedRealtime;
}
+ @UnsupportedAppUsage
public int size() {
return size;
}
@@ -460,6 +509,7 @@
* {@link #findIndex(String, int, int, int, int)} is unable to find match. Can
* also be used to subtract values from existing rows.
*/
+ @UnsupportedAppUsage
public NetworkStats combineValues(Entry entry) {
final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered,
entry.roaming, entry.defaultNetwork);
@@ -479,6 +529,7 @@
/**
* Combine all values from another {@link NetworkStats} into this object.
*/
+ @UnsupportedAppUsage
public void combineAllValues(NetworkStats another) {
NetworkStats.Entry entry = null;
for (int i = 0; i < another.size; i++) {
@@ -564,6 +615,7 @@
/**
* Return list of unique UIDs known by this data structure.
*/
+ @UnsupportedAppUsage
public int[] getUniqueUids() {
final SparseBooleanArray uids = new SparseBooleanArray();
for (int uid : this.uid) {
@@ -582,6 +634,7 @@
* Return total bytes represented by this snapshot object, usually used when
* checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
*/
+ @UnsupportedAppUsage
public long getTotalBytes() {
final Entry entry = getTotal(null);
return entry.rxBytes + entry.txBytes;
@@ -590,6 +643,7 @@
/**
* Return total of all fields represented by this snapshot object.
*/
+ @UnsupportedAppUsage
public Entry getTotal(Entry recycle) {
return getTotal(recycle, null, UID_ALL, false);
}
@@ -598,6 +652,7 @@
* Return total of all fields represented by this snapshot object matching
* the requested {@link #uid}.
*/
+ @UnsupportedAppUsage
public Entry getTotal(Entry recycle, int limitUid) {
return getTotal(recycle, null, limitUid, false);
}
@@ -610,6 +665,7 @@
return getTotal(recycle, limitIface, UID_ALL, false);
}
+ @UnsupportedAppUsage
public Entry getTotalIncludingTags(Entry recycle) {
return getTotal(recycle, null, UID_ALL, true);
}
@@ -776,14 +832,19 @@
* packet needs to be subtracted from the root UID on the base interface both for tx
* and rx traffic (http://b/12249687, http:/b/33681750).
*
+ * As for eBPF, the per uid stats is collected by different hook, the rx packets on base
+ * interface will not be counted. Thus, the adjustment on root uid is only needed in tx
+ * direction.
+ *
* <p>This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only
* {@code ConcurrentHashMap}
* @param baseTraffic Traffic on the base interfaces. Will be mutated.
* @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated.
* @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
+ * @param useBpfStats True if eBPF is in use.
*/
public static void apply464xlatAdjustments(NetworkStats baseTraffic,
- NetworkStats stackedTraffic, Map<String, String> stackedIfaces) {
+ NetworkStats stackedTraffic, Map<String, String> stackedIfaces, boolean useBpfStats) {
// Total 464xlat traffic to subtract from uid 0 on all base interfaces.
// stackedIfaces may grow afterwards, but NetworkStats will just be resized automatically.
final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size());
@@ -802,15 +863,20 @@
continue;
}
// Subtract any 464lat traffic seen for the root UID on the current base interface.
+ // However, for eBPF, the per uid stats is collected by different hook, the rx packets
+ // on base interface will not be counted. Thus, the adjustment on root uid is only
+ // needed in tx direction.
adjust.iface = baseIface;
- adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA);
+ if (!useBpfStats) {
+ adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA);
+ adjust.rxPackets = -entry.rxPackets;
+ }
adjust.txBytes = -(entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA);
- adjust.rxPackets = -entry.rxPackets;
adjust.txPackets = -entry.txPackets;
adjustments.combineValues(adjust);
- // For 464xlat traffic, xt_qtaguid only counts the bytes of the native IPv4 packet sent
- // on the stacked interface with prefix "v4-" and drops the IPv6 header size after
+ // For 464xlat traffic, per uid stats only counts the bytes of the native IPv4 packet
+ // sent on the stacked interface with prefix "v4-" and drops the IPv6 header size after
// unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes
// difference for all packets (http://b/12249687, http:/b/33681750).
entry.rxBytes += entry.rxPackets * IPV4V6_HEADER_DELTA;
@@ -829,8 +895,8 @@
* base and stacked traffic.
* @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
*/
- public void apply464xlatAdjustments(Map<String, String> stackedIfaces) {
- apply464xlatAdjustments(this, this, stackedIfaces);
+ public void apply464xlatAdjustments(Map<String, String> stackedIfaces, boolean useBpfStats) {
+ apply464xlatAdjustments(this, this, stackedIfaces, useBpfStats);
}
/**
@@ -896,21 +962,18 @@
}
/**
- * Return all rows except those attributed to the requested UID; doesn't
- * mutate the original structure.
+ * Remove all rows that match one of specified UIDs.
*/
- public NetworkStats withoutUids(int[] uids) {
- final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
-
- Entry entry = new Entry();
+ public void removeUids(int[] uids) {
+ int nextOutputEntry = 0;
for (int i = 0; i < size; i++) {
- entry = getValues(i, entry);
- if (!ArrayUtils.contains(uids, entry.uid)) {
- stats.addValues(entry);
+ if (!ArrayUtils.contains(uids, uid[i])) {
+ maybeCopyEntry(nextOutputEntry, i);
+ nextOutputEntry++;
}
}
- return stats;
+ size = nextOutputEntry;
}
/**
@@ -1085,6 +1148,7 @@
return 0;
}
+ @UnsupportedAppUsage
public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
@Override
public NetworkStats createFromParcel(Parcel in) {
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index a13ad65..d53e032 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -30,6 +30,7 @@
import static com.android.internal.util.ArrayUtils.total;
+import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.service.NetworkStatsHistoryBucketProto;
@@ -89,16 +90,23 @@
public static class Entry {
public static final long UNKNOWN = -1;
+ @UnsupportedAppUsage
public long bucketDuration;
+ @UnsupportedAppUsage
public long bucketStart;
public long activeTime;
+ @UnsupportedAppUsage
public long rxBytes;
+ @UnsupportedAppUsage
public long rxPackets;
+ @UnsupportedAppUsage
public long txBytes;
+ @UnsupportedAppUsage
public long txPackets;
public long operations;
}
+ @UnsupportedAppUsage
public NetworkStatsHistory(long bucketDuration) {
this(bucketDuration, 10, FIELD_ALL);
}
@@ -125,6 +133,7 @@
recordEntireHistory(existing);
}
+ @UnsupportedAppUsage
public NetworkStatsHistory(Parcel in) {
bucketDuration = in.readLong();
bucketStart = readLongArray(in);
@@ -210,6 +219,7 @@
return 0;
}
+ @UnsupportedAppUsage
public int size() {
return bucketCount;
}
@@ -218,6 +228,7 @@
return bucketDuration;
}
+ @UnsupportedAppUsage
public long getStart() {
if (bucketCount > 0) {
return bucketStart[0];
@@ -226,6 +237,7 @@
}
}
+ @UnsupportedAppUsage
public long getEnd() {
if (bucketCount > 0) {
return bucketStart[bucketCount - 1] + bucketDuration;
@@ -245,6 +257,7 @@
* Return index of bucket that contains or is immediately before the
* requested time.
*/
+ @UnsupportedAppUsage
public int getIndexBefore(long time) {
int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time);
if (index < 0) {
@@ -272,6 +285,7 @@
/**
* Return specific stats entry.
*/
+ @UnsupportedAppUsage
public Entry getValues(int i, Entry recycle) {
final Entry entry = recycle != null ? recycle : new Entry();
entry.bucketStart = bucketStart[i];
@@ -373,6 +387,7 @@
* Record an entire {@link NetworkStatsHistory} into this history. Usually
* for combining together stats for external reporting.
*/
+ @UnsupportedAppUsage
public void recordEntireHistory(NetworkStatsHistory input) {
recordHistory(input, Long.MIN_VALUE, Long.MAX_VALUE);
}
@@ -509,6 +524,7 @@
* Return interpolated data usage across the requested range. Interpolates
* across buckets, so values may be rounded slightly.
*/
+ @UnsupportedAppUsage
public Entry getValues(long start, long end, Entry recycle) {
return getValues(start, end, Long.MAX_VALUE, recycle);
}
@@ -517,6 +533,7 @@
* Return interpolated data usage across the requested range. Interpolates
* across buckets, so values may be rounded slightly.
*/
+ @UnsupportedAppUsage
public Entry getValues(long start, long end, long now, Entry recycle) {
final Entry entry = recycle != null ? recycle : new Entry();
entry.bucketDuration = end - start;
@@ -701,6 +718,7 @@
return writer.toString();
}
+ @UnsupportedAppUsage
public static final Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() {
@Override
public NetworkStatsHistory createFromParcel(Parcel in) {
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 74233fd..bb75c63 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -34,6 +34,7 @@
import static android.net.NetworkStats.ROAMING_YES;
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
+import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.BackupUtils;
@@ -96,6 +97,7 @@
* Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
* the given IMSI.
*/
+ @UnsupportedAppUsage
public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
return new NetworkTemplate(MATCH_MOBILE, subscriberId, null);
}
@@ -104,6 +106,7 @@
* Template to match {@link ConnectivityManager#TYPE_MOBILE} networks,
* regardless of IMSI.
*/
+ @UnsupportedAppUsage
public static NetworkTemplate buildTemplateMobileWildcard() {
return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null);
}
@@ -112,11 +115,13 @@
* Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
* regardless of SSID.
*/
+ @UnsupportedAppUsage
public static NetworkTemplate buildTemplateWifiWildcard() {
return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
}
@Deprecated
+ @UnsupportedAppUsage
public static NetworkTemplate buildTemplateWifi() {
return buildTemplateWifiWildcard();
}
@@ -133,6 +138,7 @@
* Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style
* networks together.
*/
+ @UnsupportedAppUsage
public static NetworkTemplate buildTemplateEthernet() {
return new NetworkTemplate(MATCH_ETHERNET, null, null);
}
@@ -173,6 +179,7 @@
private final int mRoaming;
private final int mDefaultNetwork;
+ @UnsupportedAppUsage
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
}
@@ -293,10 +300,12 @@
}
}
+ @UnsupportedAppUsage
public int getMatchRule() {
return mMatchRule;
}
+ @UnsupportedAppUsage
public String getSubscriberId() {
return mSubscriberId;
}
@@ -460,6 +469,7 @@
* active merge set [A,B], we'd return a new template that primarily matches
* A, but also matches B.
*/
+ @UnsupportedAppUsage
public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) {
// Requested template subscriber is part of the merge group; return
@@ -471,6 +481,7 @@
}
}
+ @UnsupportedAppUsage
public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
@Override
public NetworkTemplate createFromParcel(Parcel in) {
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index f033268..22dd4fc 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -19,6 +19,7 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
import android.app.DownloadManager;
import android.app.backup.BackupManager;
import android.app.usage.NetworkStatsManager;
@@ -138,9 +139,12 @@
public static final int TAG_SYSTEM_GPS = 0xFFFFFF44;
/** @hide */
public static final int TAG_SYSTEM_PAC = 0xFFFFFF45;
+ /** @hide */
+ public static final int TAG_SYSTEM_DHCP_SERVER = 0xFFFFFF46;
private static INetworkStatsService sStatsService;
+ @UnsupportedAppUsage
private synchronized static INetworkStatsService getStatsService() {
if (sStatsService == null) {
sStatsService = INetworkStatsService.Stub.asInterface(
@@ -536,6 +540,7 @@
}
/** {@hide} */
+ @UnsupportedAppUsage
public static long getMobileTcpRxPackets() {
long total = 0;
for (String iface : getMobileIfaces()) {
@@ -551,6 +556,7 @@
}
/** {@hide} */
+ @UnsupportedAppUsage
public static long getMobileTcpTxPackets() {
long total = 0;
for (String iface : getMobileIfaces()) {
@@ -584,6 +590,7 @@
}
/** {@hide} */
+ @UnsupportedAppUsage
public static long getTxBytes(String iface) {
try {
return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES);
@@ -593,6 +600,7 @@
}
/** {@hide} */
+ @UnsupportedAppUsage
public static long getRxBytes(String iface) {
try {
return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES);
@@ -948,6 +956,7 @@
* Interfaces are never removed from this list, so counters should always be
* monotonic.
*/
+ @UnsupportedAppUsage
private static String[] getMobileIfaces() {
try {
return getStatsService().getMobileIfaces();
diff --git a/core/java/android/net/UidRange.aidl b/core/java/android/net/UidRange.aidl
new file mode 100644
index 0000000..f70fc8e
--- /dev/null
+++ b/core/java/android/net/UidRange.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2018 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;
+
+/**
+ * An inclusive range of UIDs.
+ *
+ * {@hide}
+ */
+parcelable UidRange;
\ No newline at end of file
diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java
index bccaf60..9ba17ed 100644
--- a/core/java/android/net/nsd/NsdServiceInfo.java
+++ b/core/java/android/net/nsd/NsdServiceInfo.java
@@ -17,6 +17,7 @@
package android.net.nsd;
import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
import android.os.Parcelable;
import android.os.Parcel;
import android.text.TextUtils;
@@ -185,6 +186,7 @@
}
/** @hide */
+ @UnsupportedAppUsage
public void setAttribute(String key, byte[] value) {
if (TextUtils.isEmpty(key)) {
throw new IllegalArgumentException("Key cannot be empty");
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index c4d08c7..0a7cff6 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -113,11 +113,12 @@
/**
* Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}.
- * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map)
+ * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map, boolean)
*/
public static void apply464xlatAdjustments(NetworkStats baseTraffic,
- NetworkStats stackedTraffic) {
- NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces);
+ NetworkStats stackedTraffic, boolean useBpfStats) {
+ NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces,
+ useBpfStats);
}
@VisibleForTesting
@@ -194,7 +195,7 @@
reader.finishLine();
}
} catch (NullPointerException|NumberFormatException e) {
- throw new ProtocolException("problem parsing stats", e);
+ throw protocolExceptionWithCause("problem parsing stats", e);
} finally {
IoUtils.closeQuietly(reader);
StrictMode.setThreadPolicy(savedPolicy);
@@ -244,7 +245,7 @@
reader.finishLine();
}
} catch (NullPointerException|NumberFormatException e) {
- throw new ProtocolException("problem parsing stats", e);
+ throw protocolExceptionWithCause("problem parsing stats", e);
} finally {
IoUtils.closeQuietly(reader);
StrictMode.setThreadPolicy(savedPolicy);
@@ -263,7 +264,7 @@
// No locking here: apply464xlatAdjustments behaves fine with an add-only ConcurrentHashMap.
// TODO: remove this and only apply adjustments in NetworkStatsService.
- stats.apply464xlatAdjustments(sStackedIfaces);
+ stats.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats);
return stats;
}
@@ -341,7 +342,7 @@
reader.finishLine();
}
} catch (NullPointerException|NumberFormatException e) {
- throw new ProtocolException("problem parsing idx " + idx, e);
+ throw protocolExceptionWithCause("problem parsing idx " + idx, e);
} finally {
IoUtils.closeQuietly(reader);
StrictMode.setThreadPolicy(savedPolicy);
@@ -378,4 +379,10 @@
@VisibleForTesting
public static native int nativeReadNetworkStatsDev(NetworkStats stats);
+
+ private static ProtocolException protocolExceptionWithCause(String message, Throwable cause) {
+ ProtocolException pe = new ProtocolException(message);
+ pe.initCause(cause);
+ return pe;
+ }
}
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index c15b7ee..b708735 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -32,8 +32,8 @@
#include <utils/misc.h>
#include "android-base/unique_fd.h"
-#include "bpf/BpfNetworkStats.h"
#include "bpf/BpfUtils.h"
+#include "netdbpf/BpfNetworkStats.h"
using android::bpf::hasBpfSupport;
using android::bpf::parseBpfNetworkStatsDetail;
@@ -175,7 +175,7 @@
}
}
s.tag = rawTag >> 32;
- if (limitTag != -1 && s.tag != limitTag) {
+ if (limitTag != -1 && s.tag != static_cast<uint32_t>(limitTag)) {
//ALOGI("skipping due to tag: %s", buffer);
continue;
}
@@ -188,7 +188,7 @@
if (sscanf(pos, "%u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64,
&s.uid, &s.set, &s.rxBytes, &s.rxPackets,
&s.txBytes, &s.txPackets) == 6) {
- if (limitUid != -1 && limitUid != s.uid) {
+ if (limitUid != -1 && static_cast<uint32_t>(limitUid) != s.uid) {
//ALOGI("skipping due to uid: %s", buffer);
continue;
}
@@ -285,10 +285,6 @@
static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
jboolean useBpfStats) {
- ScopedUtfChars path8(env, path);
- if (path8.c_str() == NULL) {
- return -1;
- }
std::vector<std::string> limitIfaces;
if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
@@ -308,6 +304,11 @@
if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
return -1;
} else {
+ ScopedUtfChars path8(env, path);
+ if (path8.c_str() == NULL) {
+ ALOGE("the qtaguid legacy path is invalid: %s", path8.c_str());
+ return -1;
+ }
if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
limitUid, path8.c_str()) < 0)
return -1;
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 60f1877..126bf65 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -19,15 +19,17 @@
import static android.Manifest.permission.DUMP;
import static android.net.IpSecManager.INVALID_RESOURCE_ID;
import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.AF_UNSPEC;
import static android.system.OsConstants.EINVAL;
import static android.system.OsConstants.IPPROTO_UDP;
import static android.system.OsConstants.SOCK_DGRAM;
+
import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.Context;
-import android.net.ConnectivityManager;
import android.net.IIpSecService;
import android.net.INetd;
import android.net.IpSecAlgorithm;
@@ -44,7 +46,6 @@
import android.net.TrafficStats;
import android.net.util.NetdService;
import android.os.Binder;
-import android.os.DeadSystemException;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -62,17 +63,19 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import libcore.io.IoUtils;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
-import libcore.io.IoUtils;
-
/**
* A service to manage multiple clients that want to access the IpSec API. The service is
* responsible for maintaining a list of clients and managing the resources (and related quotas)
@@ -89,9 +92,8 @@
private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
private static final String NETD_SERVICE_NAME = "netd";
- private static final int[] DIRECTIONS =
- new int[] {IpSecManager.DIRECTION_OUT, IpSecManager.DIRECTION_IN};
- private static final String[] WILDCARD_ADDRESSES = new String[]{"0.0.0.0", "::"};
+ private static final int[] ADDRESS_FAMILIES =
+ new int[] {OsConstants.AF_INET, OsConstants.AF_INET6};
private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms
private static final int MAX_PORT_BIND_ATTEMPTS = 10;
@@ -615,12 +617,13 @@
mSrvConfig
.getNetdInstance()
.ipSecDeleteSecurityAssociation(
- mResourceId,
+ uid,
mConfig.getSourceAddress(),
mConfig.getDestinationAddress(),
spi,
mConfig.getMarkValue(),
- mConfig.getMarkMask());
+ mConfig.getMarkMask(),
+ mConfig.getXfrmInterfaceId());
} catch (RemoteException | ServiceSpecificException e) {
Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e);
}
@@ -682,7 +685,8 @@
mSrvConfig
.getNetdInstance()
.ipSecDeleteSecurityAssociation(
- mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0);
+ uid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */,
+ 0 /* mask */, 0 /* if_id */);
}
} catch (ServiceSpecificException | RemoteException e) {
Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e);
@@ -794,6 +798,8 @@
private final int mIkey;
private final int mOkey;
+ private final int mIfId;
+
TunnelInterfaceRecord(
int resourceId,
String interfaceName,
@@ -801,7 +807,8 @@
String localAddr,
String remoteAddr,
int ikey,
- int okey) {
+ int okey,
+ int intfId) {
super(resourceId);
mInterfaceName = interfaceName;
@@ -810,6 +817,7 @@
mRemoteAddress = remoteAddr;
mIkey = ikey;
mOkey = okey;
+ mIfId = intfId;
}
/** always guarded by IpSecService#this */
@@ -819,16 +827,24 @@
// Teardown VTI
// Delete global policies
try {
- mSrvConfig.getNetdInstance().removeVirtualTunnelInterface(mInterfaceName);
+ final INetd netd = mSrvConfig.getNetdInstance();
+ netd.ipSecRemoveTunnelInterface(mInterfaceName);
- for(String wildcardAddr : WILDCARD_ADDRESSES) {
- for (int direction : DIRECTIONS) {
- int mark = (direction == IpSecManager.DIRECTION_IN) ? mIkey : mOkey;
- mSrvConfig
- .getNetdInstance()
- .ipSecDeleteSecurityPolicy(
- 0, direction, wildcardAddr, wildcardAddr, mark, 0xffffffff);
- }
+ for (int selAddrFamily : ADDRESS_FAMILIES) {
+ netd.ipSecDeleteSecurityPolicy(
+ uid,
+ selAddrFamily,
+ IpSecManager.DIRECTION_OUT,
+ mOkey,
+ 0xffffffff,
+ mIfId);
+ netd.ipSecDeleteSecurityPolicy(
+ uid,
+ selAddrFamily,
+ IpSecManager.DIRECTION_IN,
+ mIkey,
+ 0xffffffff,
+ mIfId);
}
} catch (ServiceSpecificException | RemoteException e) {
Log.e(
@@ -870,6 +886,10 @@
return mOkey;
}
+ public int getIfId() {
+ return mIfId;
+ }
+
@Override
protected ResourceTracker getResourceTracker() {
return getUserRecord().mTunnelQuotaTracker;
@@ -1080,7 +1100,8 @@
}
checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
- UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
+ int callingUid = Binder.getCallingUid();
+ UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
final int resourceId = mNextResourceId++;
int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
@@ -1093,7 +1114,7 @@
spi =
mSrvConfig
.getNetdInstance()
- .ipSecAllocateSpi(resourceId, "", destinationAddress, requestedSpi);
+ .ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi);
Log.d(TAG, "Allocated SPI " + spi);
userRecord.mSpiRecords.put(
resourceId,
@@ -1215,7 +1236,8 @@
OsConstants.UDP_ENCAP,
OsConstants.UDP_ENCAP_ESPINUDP);
- mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner(sockFd, callingUid);
+ mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner(
+ new ParcelFileDescriptor(sockFd), callingUid);
if (port != 0) {
Log.v(TAG, "Binding to port " + port);
Os.bind(sockFd, INADDR_ANY, port);
@@ -1261,7 +1283,8 @@
// TODO: Check that underlying network exists, and IP addresses not assigned to a different
// network (b/72316676).
- UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
+ int callerUid = Binder.getCallingUid();
+ UserRecord userRecord = mUserResourceTracker.getUserRecord(callerUid);
if (!userRecord.mTunnelQuotaTracker.isAvailable()) {
return new IpSecTunnelInterfaceResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
}
@@ -1276,25 +1299,31 @@
// Create VTI
// Add inbound/outbound global policies
// (use reqid = 0)
- mSrvConfig
- .getNetdInstance()
- .addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey);
+ final INetd netd = mSrvConfig.getNetdInstance();
+ netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
- for(String wildcardAddr : WILDCARD_ADDRESSES) {
- for (int direction : DIRECTIONS) {
- int mark = (direction == IpSecManager.DIRECTION_OUT) ? okey : ikey;
-
- mSrvConfig
- .getNetdInstance()
- .ipSecAddSecurityPolicy(
- 0, // Use 0 for reqId
- direction,
- wildcardAddr,
- wildcardAddr,
- 0,
- mark,
- 0xffffffff);
- }
+ for (int selAddrFamily : ADDRESS_FAMILIES) {
+ // Always send down correct local/remote addresses for template.
+ netd.ipSecAddSecurityPolicy(
+ callerUid,
+ selAddrFamily,
+ IpSecManager.DIRECTION_OUT,
+ localAddr,
+ remoteAddr,
+ 0,
+ okey,
+ 0xffffffff,
+ resourceId);
+ netd.ipSecAddSecurityPolicy(
+ callerUid,
+ selAddrFamily,
+ IpSecManager.DIRECTION_IN,
+ remoteAddr,
+ localAddr,
+ 0,
+ ikey,
+ 0xffffffff,
+ resourceId);
}
userRecord.mTunnelInterfaceRecords.put(
@@ -1307,7 +1336,8 @@
localAddr,
remoteAddr,
ikey,
- okey),
+ okey,
+ resourceId),
binder));
return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName);
} catch (RemoteException e) {
@@ -1417,6 +1447,17 @@
+ "or Encryption algorithms");
}
+ private int getFamily(String inetAddress) {
+ int family = AF_UNSPEC;
+ InetAddress checkAddress = NetworkUtils.numericToInetAddress(inetAddress);
+ if (checkAddress instanceof Inet4Address) {
+ family = AF_INET;
+ } else if (checkAddress instanceof Inet6Address) {
+ family = AF_INET6;
+ }
+ return family;
+ }
+
/**
* Checks an IpSecConfig parcel to ensure that the contents are sane and throws an
* IllegalArgumentException if they are not.
@@ -1470,6 +1511,26 @@
// Require a valid source address for all transforms.
checkInetAddress(config.getSourceAddress());
+ // Check to ensure source and destination have the same address family.
+ String sourceAddress = config.getSourceAddress();
+ String destinationAddress = config.getDestinationAddress();
+ int sourceFamily = getFamily(sourceAddress);
+ int destinationFamily = getFamily(destinationAddress);
+ if (sourceFamily != destinationFamily) {
+ throw new IllegalArgumentException(
+ "Source address ("
+ + sourceAddress
+ + ") and destination address ("
+ + destinationAddress
+ + ") have different address families.");
+ }
+
+ // Throw an error if UDP Encapsulation is not used in IPv4.
+ if (config.getEncapType() != IpSecTransform.ENCAP_NONE && sourceFamily != AF_INET) {
+ throw new IllegalArgumentException(
+ "UDP Encapsulation is not supported for this address family");
+ }
+
switch (config.getMode()) {
case IpSecTransform.MODE_TRANSPORT:
break;
@@ -1479,13 +1540,16 @@
throw new IllegalArgumentException(
"Invalid IpSecTransform.mode: " + config.getMode());
}
+
+ config.setMarkValue(0);
+ config.setMarkMask(0);
}
+ private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS;
+
private void enforceTunnelPermissions(String callingPackage) {
checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels");
- switch (getAppOpsManager().noteOp(
- AppOpsManager.OP_MANAGE_IPSEC_TUNNELS,
- Binder.getCallingUid(), callingPackage)) {
+ switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
case AppOpsManager.MODE_DEFAULT:
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService");
@@ -1521,7 +1585,7 @@
mSrvConfig
.getNetdInstance()
.ipSecAddSecurityAssociation(
- resourceId,
+ Binder.getCallingUid(),
c.getMode(),
c.getSourceAddress(),
c.getDestinationAddress(),
@@ -1540,7 +1604,8 @@
(authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
encapType,
encapLocalPort,
- encapRemotePort);
+ encapRemotePort,
+ c.getXfrmInterfaceId());
}
/**
@@ -1612,13 +1677,14 @@
@Override
public synchronized void applyTransportModeTransform(
ParcelFileDescriptor socket, int direction, int resourceId) throws RemoteException {
- UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
+ int callingUid = Binder.getCallingUid();
+ UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
checkDirection(direction);
// Get transform record; if no transform is found, will throw IllegalArgumentException
TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId);
// TODO: make this a function.
- if (info.pid != getCallingPid() || info.uid != getCallingUid()) {
+ if (info.pid != getCallingPid() || info.uid != callingUid) {
throw new SecurityException("Only the owner of an IpSec Transform may apply it!");
}
@@ -1631,8 +1697,8 @@
mSrvConfig
.getNetdInstance()
.ipSecApplyTransportModeTransform(
- socket.getFileDescriptor(),
- resourceId,
+ socket,
+ callingUid,
direction,
c.getSourceAddress(),
c.getDestinationAddress(),
@@ -1650,7 +1716,7 @@
throws RemoteException {
mSrvConfig
.getNetdInstance()
- .ipSecRemoveTransportModeTransform(socket.getFileDescriptor());
+ .ipSecRemoveTransportModeTransform(socket);
}
/**
@@ -1664,7 +1730,8 @@
enforceTunnelPermissions(callingPackage);
checkDirection(direction);
- UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
+ int callingUid = Binder.getCallingUid();
+ UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
// Get transform record; if no transform is found, will throw IllegalArgumentException
TransformRecord transformInfo =
@@ -1689,31 +1756,53 @@
SpiRecord spiRecord = userRecord.mSpiRecords.getResourceOrThrow(c.getSpiResourceId());
int mark =
- (direction == IpSecManager.DIRECTION_IN)
- ? tunnelInterfaceInfo.getIkey()
- : tunnelInterfaceInfo.getOkey();
+ (direction == IpSecManager.DIRECTION_OUT)
+ ? tunnelInterfaceInfo.getOkey()
+ : tunnelInterfaceInfo.getIkey();
try {
- c.setMarkValue(mark);
- c.setMarkMask(0xffffffff);
+ // Default to using the invalid SPI of 0 for inbound SAs. This allows policies to skip
+ // SPI matching as part of the template resolution.
+ int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
+ c.setXfrmInterfaceId(tunnelInterfaceInfo.getIfId());
+
+ // TODO: enable this when UPDSA supports updating marks. Adding kernel support upstream
+ // (and backporting) would allow us to narrow the mark space, and ensure that the SA
+ // and SPs have matching marks (as VTI are meant to be built).
+ // Currently update does nothing with marks. Leave empty (defaulting to 0) to ensure the
+ // config matches the actual allocated resources in the kernel.
+ // All SAs will have zero marks (from creation time), and any policy that matches the
+ // same src/dst could match these SAs. Non-IpSecService governed processes that
+ // establish floating policies with the same src/dst may result in undefined
+ // behavior. This is generally limited to vendor code due to the permissions
+ // (CAP_NET_ADMIN) required.
+ //
+ // c.setMarkValue(mark);
+ // c.setMarkMask(0xffffffff);
if (direction == IpSecManager.DIRECTION_OUT) {
// Set output mark via underlying network (output only)
c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork());
- // If outbound, also add SPI to the policy.
- for(String wildcardAddr : WILDCARD_ADDRESSES) {
- mSrvConfig
- .getNetdInstance()
- .ipSecUpdateSecurityPolicy(
- 0, // Use 0 for reqId
- direction,
- wildcardAddr,
- wildcardAddr,
- transformInfo.getSpiRecord().getSpi(),
- mark,
- 0xffffffff);
- }
+ // Set outbound SPI only. We want inbound to use any valid SA (old, new) on rekeys,
+ // but want to guarantee outbound packets are sent over the new SA.
+ spi = transformInfo.getSpiRecord().getSpi();
+ }
+
+ // Always update the policy with the relevant XFRM_IF_ID
+ for (int selAddrFamily : ADDRESS_FAMILIES) {
+ mSrvConfig
+ .getNetdInstance()
+ .ipSecUpdateSecurityPolicy(
+ callingUid,
+ selAddrFamily,
+ direction,
+ transformInfo.getConfig().getSourceAddress(),
+ transformInfo.getConfig().getDestinationAddress(),
+ spi, // If outbound, also add SPI to the policy.
+ mark, // Must always set policy mark; ikey/okey for VTIs
+ 0xffffffff,
+ c.getXfrmInterfaceId());
}
// Update SA with tunnel mark (ikey or okey based on direction)
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index a16dcf3..a2e7e0c 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -352,7 +352,7 @@
// Clear UID from current stats snapshot
if (mLastSnapshot != null) {
- mLastSnapshot = mLastSnapshot.withoutUids(uids);
+ mLastSnapshot.removeUids(uids);
}
final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null;
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index fec510f..8237185 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -159,9 +159,10 @@
static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
+ // Perform polling and persist all (FLAG_PERSIST_ALL).
private static final int MSG_PERFORM_POLL = 1;
- private static final int MSG_UPDATE_IFACES = 2;
- private static final int MSG_REGISTER_GLOBAL_ALERT = 3;
+ // Perform polling, persist network, and register the global alert again.
+ private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2;
/** Flags to control detail level of poll event. */
private static final int FLAG_PERSIST_NETWORK = 0x1;
@@ -169,6 +170,14 @@
private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
private static final int FLAG_PERSIST_FORCE = 0x100;
+ /**
+ * When global alert quota is high, wait for this delay before processing each polling,
+ * and do not schedule further polls once there is already one queued.
+ * This avoids firing the global alert too often on devices with high transfer speeds and
+ * high quota.
+ */
+ private static final int PERFORM_POLL_DELAY_MS = 1000;
+
private static final String TAG_NETSTATS_ERROR = "netstats_error";
private final Context mContext;
@@ -325,6 +334,7 @@
wakeLock, getDefaultClock(), TelephonyManager.getDefault(),
new DefaultNetworkStatsSettings(context), new NetworkStatsObservers(),
getDefaultSystemDir(), getDefaultBaseDir());
+ service.registerLocalService();
HandlerThread handlerThread = new HandlerThread(TAG);
Handler.Callback callback = new HandlerCallback(service);
@@ -334,6 +344,8 @@
return service;
}
+ // This must not be called outside of tests, even within the same package, as this constructor
+ // does not register the local service. Use the create() helper above.
@VisibleForTesting
NetworkStatsService(Context context, INetworkManagementService networkManager,
AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock,
@@ -350,7 +362,9 @@
mSystemDir = checkNotNull(systemDir, "missing systemDir");
mBaseDir = checkNotNull(baseDir, "missing baseDir");
mUseBpfTrafficStats = new File("/sys/fs/bpf/traffic_uid_stats_map").exists();
+ }
+ private void registerLocalService() {
LocalServices.addService(NetworkStatsManagerInternal.class,
new NetworkStatsManagerInternalImpl());
}
@@ -916,7 +930,7 @@
}
// Create baseline stats
- mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL, FLAG_PERSIST_ALL));
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL));
return normalizedRequest;
}
@@ -1057,13 +1071,12 @@
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
- // kick off background poll to collect network stats; UID stats
- // are handled during normal polling interval.
- final int flags = FLAG_PERSIST_NETWORK;
- mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget();
-
- // re-arm global alert for next update
- mHandler.obtainMessage(MSG_REGISTER_GLOBAL_ALERT).sendToTarget();
+ // kick off background poll to collect network stats unless there is already
+ // such a call pending; UID stats are handled during normal polling interval.
+ if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) {
+ mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT,
+ PERFORM_POLL_DELAY_MS);
+ }
}
}
};
@@ -1613,7 +1626,8 @@
// fold tethering stats and operations into uid snapshot
final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID);
tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL);
- NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot);
+ NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot,
+ mUseBpfTrafficStats);
uidSnapshot.combineAllValues(tetherSnapshot);
final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
@@ -1623,7 +1637,8 @@
final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID);
if (vtStats != null) {
vtStats.filter(UID_ALL, ifaces, TAG_ALL);
- NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats);
+ NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats,
+ mUseBpfTrafficStats);
uidSnapshot.combineAllValues(vtStats);
}
@@ -1675,15 +1690,11 @@
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_PERFORM_POLL: {
- final int flags = msg.arg1;
- mService.performPoll(flags);
+ mService.performPoll(FLAG_PERSIST_ALL);
return true;
}
- case MSG_UPDATE_IFACES: {
- mService.updateIfaces(null);
- return true;
- }
- case MSG_REGISTER_GLOBAL_ALERT: {
+ case MSG_PERFORM_POLL_REGISTER_ALERT: {
+ mService.performPoll(FLAG_PERSIST_NETWORK);
mService.registerGlobalAlert();
return true;
}
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 3302dea..649f1a5 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -30,8 +30,8 @@
#include <utils/Log.h>
#include "android-base/unique_fd.h"
-#include "bpf/BpfNetworkStats.h"
#include "bpf/BpfUtils.h"
+#include "netdbpf/BpfNetworkStats.h"
using android::bpf::Stats;
using android::bpf::hasBpfSupport;