[automerger skipped] DO NOT MERGE - Merge Pie Bonito/Sargo into master. am: e963030676 -s ours
am: bd1a8961e2 -s ours
am skip reason: subject contains skip directive
Change-Id: I862d40111b2e525e5838bf09e169c8c3f416633b
diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java
index ac9a5a3..0ac8f7e 100644
--- a/core/java/android/net/DataUsageRequest.java
+++ b/core/java/android/net/DataUsageRequest.java
@@ -69,7 +69,7 @@
dest.writeLong(thresholdInBytes);
}
- public static final Creator<DataUsageRequest> CREATOR =
+ public static final @android.annotation.NonNull Creator<DataUsageRequest> CREATOR =
new Creator<DataUsageRequest>() {
@Override
public DataUsageRequest createFromParcel(Parcel in) {
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index 8034bb6..38d9883 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -191,7 +191,7 @@
}
/** Parcelable Creator */
- public static final Parcelable.Creator<IpSecAlgorithm> CREATOR =
+ public static final @android.annotation.NonNull Parcelable.Creator<IpSecAlgorithm> CREATOR =
new Parcelable.Creator<IpSecAlgorithm>() {
public IpSecAlgorithm createFromParcel(Parcel in) {
final String name = in.readString();
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
index 3552655..a64014f 100644
--- a/core/java/android/net/IpSecConfig.java
+++ b/core/java/android/net/IpSecConfig.java
@@ -322,7 +322,7 @@
return strBuilder.toString();
}
- public static final Parcelable.Creator<IpSecConfig> CREATOR =
+ public static final @android.annotation.NonNull Parcelable.Creator<IpSecConfig> CREATOR =
new Parcelable.Creator<IpSecConfig>() {
public IpSecConfig createFromParcel(Parcel in) {
return new IpSecConfig(in);
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 889e9bc..83813da 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -19,10 +19,13 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -720,6 +723,7 @@
* to create Network objects which are accessible to the Android system.
* @hide
*/
+ @SystemApi
public static final class IpSecTunnelInterface implements AutoCloseable {
private final String mOpPackageName;
private final IIpSecService mService;
@@ -746,6 +750,8 @@
* @param prefixLen length of the InetAddress prefix
* @hide
*/
+ @SystemApi
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
try {
@@ -767,6 +773,8 @@
* @param prefixLen length of the InetAddress prefix
* @hide
*/
+ @SystemApi
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
try {
@@ -880,7 +888,9 @@
* @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
* @hide
*/
+ @SystemApi
@NonNull
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
@NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)
@@ -910,6 +920,8 @@
* layer failure.
* @hide
*/
+ @SystemApi
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel,
@PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
diff --git a/core/java/android/net/IpSecSpiResponse.java b/core/java/android/net/IpSecSpiResponse.java
index 71dfa03..f99e570 100644
--- a/core/java/android/net/IpSecSpiResponse.java
+++ b/core/java/android/net/IpSecSpiResponse.java
@@ -65,7 +65,7 @@
spi = in.readInt();
}
- public static final Parcelable.Creator<IpSecSpiResponse> CREATOR =
+ public static final @android.annotation.NonNull Parcelable.Creator<IpSecSpiResponse> CREATOR =
new Parcelable.Creator<IpSecSpiResponse>() {
public IpSecSpiResponse createFromParcel(Parcel in) {
return new IpSecSpiResponse(in);
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index a12df28..36111f2 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -21,8 +21,11 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -480,7 +483,9 @@
* @throws IOException indicating other errors
* @hide
*/
+ @SystemApi
@NonNull
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public IpSecTransform buildTunnelModeTransform(
@NonNull InetAddress sourceAddress,
diff --git a/core/java/android/net/IpSecTransformResponse.java b/core/java/android/net/IpSecTransformResponse.java
index cfc1762..a384889 100644
--- a/core/java/android/net/IpSecTransformResponse.java
+++ b/core/java/android/net/IpSecTransformResponse.java
@@ -60,7 +60,7 @@
resourceId = in.readInt();
}
- public static final Parcelable.Creator<IpSecTransformResponse> CREATOR =
+ public static final @android.annotation.NonNull Parcelable.Creator<IpSecTransformResponse> CREATOR =
new Parcelable.Creator<IpSecTransformResponse>() {
public IpSecTransformResponse createFromParcel(Parcel in) {
return new IpSecTransformResponse(in);
diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.java b/core/java/android/net/IpSecTunnelInterfaceResponse.java
index c23d831..e3411e0 100644
--- a/core/java/android/net/IpSecTunnelInterfaceResponse.java
+++ b/core/java/android/net/IpSecTunnelInterfaceResponse.java
@@ -65,7 +65,7 @@
interfaceName = in.readString();
}
- public static final Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR =
+ public static final @android.annotation.NonNull Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR =
new Parcelable.Creator<IpSecTunnelInterfaceResponse>() {
public IpSecTunnelInterfaceResponse createFromParcel(Parcel in) {
return new IpSecTunnelInterfaceResponse(in);
diff --git a/core/java/android/net/IpSecUdpEncapResponse.java b/core/java/android/net/IpSecUdpEncapResponse.java
index 4679267..4e7ba9b 100644
--- a/core/java/android/net/IpSecUdpEncapResponse.java
+++ b/core/java/android/net/IpSecUdpEncapResponse.java
@@ -83,7 +83,7 @@
fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
}
- public static final Parcelable.Creator<IpSecUdpEncapResponse> CREATOR =
+ public static final @android.annotation.NonNull Parcelable.Creator<IpSecUdpEncapResponse> CREATOR =
new Parcelable.Creator<IpSecUdpEncapResponse>() {
public IpSecUdpEncapResponse createFromParcel(Parcel in) {
return new IpSecUdpEncapResponse(in);
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 27e0414..e892b65 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -18,7 +18,6 @@
import static android.os.Process.CLAT_UID;
-import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -34,7 +33,6 @@
import java.io.CharArrayWriter;
import java.io.PrintWriter;
import java.util.Arrays;
-import java.util.function.Predicate;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
@@ -995,33 +993,23 @@
if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) {
return;
}
- filter(e -> (limitUid == UID_ALL || limitUid == e.uid)
- && (limitTag == TAG_ALL || limitTag == e.tag)
- && (limitIfaces == INTERFACES_ALL
- || ArrayUtils.contains(limitIfaces, e.iface)));
- }
- /**
- * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}.
- *
- * <p>This mutates the original structure in place.
- */
- public void filterDebugEntries() {
- filter(e -> e.set < SET_DEBUG_START);
- }
-
- private void filter(Predicate<Entry> predicate) {
Entry entry = new Entry();
int nextOutputEntry = 0;
for (int i = 0; i < size; i++) {
entry = getValues(i, entry);
- if (predicate.test(entry)) {
- if (nextOutputEntry != i) {
- setValues(nextOutputEntry, entry);
- }
+ final boolean matches =
+ (limitUid == UID_ALL || limitUid == entry.uid)
+ && (limitTag == TAG_ALL || limitTag == entry.tag)
+ && (limitIfaces == INTERFACES_ALL
+ || ArrayUtils.contains(limitIfaces, entry.iface));
+
+ if (matches) {
+ setValues(nextOutputEntry, entry);
nextOutputEntry++;
}
}
+
size = nextOutputEntry;
}
@@ -1165,7 +1153,7 @@
}
@UnsupportedAppUsage
- public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
+ public static final @android.annotation.NonNull Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
@Override
public NetworkStats createFromParcel(Parcel in) {
return new NetworkStats(in);
@@ -1187,217 +1175,133 @@
/**
* VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface.
*
- * <p>This method should only be called on delta NetworkStats. Do not call this method on a
- * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change
- * over time.
+ * This method should only be called on delta NetworkStats. Do not call this method on a
+ * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may
+ * change over time.
*
- * <p>This method performs adjustments for one active VPN package and one VPN iface at a time.
+ * This method performs adjustments for one active VPN package and one VPN iface at a time.
+ *
+ * It is possible for the VPN software to use multiple underlying networks. This method
+ * only migrates traffic for the primary underlying network.
*
* @param tunUid uid of the VPN application
* @param tunIface iface of the vpn tunnel
- * @param underlyingIfaces underlying network ifaces used by the VPN application
+ * @param underlyingIface the primary underlying network iface used by the VPN application
+ * @return true if it successfully adjusts the accounting for VPN, false otherwise
*/
- public void migrateTun(int tunUid, @NonNull String tunIface,
- @NonNull String[] underlyingIfaces) {
- // Combined usage by all apps using VPN.
- final Entry tunIfaceTotal = new Entry();
- // Usage by VPN, grouped by its {@code underlyingIfaces}.
- final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length];
- // Usage by VPN, summed across all its {@code underlyingIfaces}.
- final Entry underlyingIfacesTotal = new Entry();
+ public boolean migrateTun(int tunUid, String tunIface, String underlyingIface) {
+ Entry tunIfaceTotal = new Entry();
+ Entry underlyingIfaceTotal = new Entry();
- for (int i = 0; i < perInterfaceTotal.length; i++) {
- perInterfaceTotal[i] = new Entry();
- }
+ tunAdjustmentInit(tunUid, tunIface, underlyingIface, tunIfaceTotal, underlyingIfaceTotal);
- tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal,
- underlyingIfacesTotal);
-
- // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app.
- // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression.
+ // If tunIface < underlyingIface, it leaves the overhead traffic in the VPN app.
+ // If tunIface > underlyingIface, the VPN app doesn't get credit for data compression.
// Negative stats should be avoided.
- final Entry[] moved =
- addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal,
- perInterfaceTotal, underlyingIfacesTotal);
- deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved);
+ Entry pool = tunGetPool(tunIfaceTotal, underlyingIfaceTotal);
+ if (pool.isEmpty()) {
+ return true;
+ }
+ Entry moved =
+ addTrafficToApplications(tunUid, tunIface, underlyingIface, tunIfaceTotal, pool);
+ deductTrafficFromVpnApp(tunUid, underlyingIface, moved);
+
+ if (!moved.isEmpty()) {
+ Slog.wtf(TAG, "Failed to deduct underlying network traffic from VPN package. Moved="
+ + moved);
+ return false;
+ }
+ return true;
}
/**
* Initializes the data used by the migrateTun() method.
*
- * <p>This is the first pass iteration which does the following work:
- *
- * <ul>
- * <li>Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and
- * background).
- * <li>Adds up all the traffic through tun0 excluding traffic from the vpn app itself.
- * </ul>
- *
- * @param tunUid uid of the VPN application
- * @param tunIface iface of the vpn tunnel
- * @param underlyingIfaces underlying network ifaces used by the VPN application
- * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN
- * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code
- * underlyingIfaces}
- * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its
- * {@code underlyingIfaces}
+ * This is the first pass iteration which does the following work:
+ * (1) Adds up all the traffic through the tunUid's underlyingIface
+ * (both foreground and background).
+ * (2) Adds up all the traffic through tun0 excluding traffic from the vpn app itself.
*/
- private void tunAdjustmentInit(int tunUid, @NonNull String tunIface,
- @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal,
- @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
- final Entry recycle = new Entry();
+ private void tunAdjustmentInit(int tunUid, String tunIface, String underlyingIface,
+ Entry tunIfaceTotal, Entry underlyingIfaceTotal) {
+ Entry recycle = new Entry();
for (int i = 0; i < size; i++) {
getValues(i, recycle);
if (recycle.uid == UID_ALL) {
throw new IllegalStateException(
"Cannot adjust VPN accounting on an iface aggregated NetworkStats.");
- }
- if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) {
+ } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) {
throw new IllegalStateException(
"Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*");
}
- if (recycle.tag != TAG_NONE) {
- // TODO(b/123666283): Take all tags for tunUid into account.
- continue;
+
+ if (recycle.uid == tunUid && recycle.tag == TAG_NONE
+ && Objects.equals(underlyingIface, recycle.iface)) {
+ underlyingIfaceTotal.add(recycle);
}
- if (recycle.uid == tunUid) {
- // Add up traffic through tunUid's underlying interfaces.
- for (int j = 0; j < underlyingIfaces.length; j++) {
- if (Objects.equals(underlyingIfaces[j], recycle.iface)) {
- perInterfaceTotal[j].add(recycle);
- underlyingIfacesTotal.add(recycle);
- break;
- }
- }
- } else if (tunIface.equals(recycle.iface)) {
+ if (recycle.uid != tunUid && recycle.tag == TAG_NONE
+ && Objects.equals(tunIface, recycle.iface)) {
// Add up all tunIface traffic excluding traffic from the vpn app itself.
tunIfaceTotal.add(recycle);
}
}
}
- /**
- * Distributes traffic across apps that are using given {@code tunIface}, and returns the total
- * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}.
- *
- * @param tunUid uid of the VPN application
- * @param tunIface iface of the vpn tunnel
- * @param underlyingIfaces underlying network ifaces used by the VPN application
- * @param tunIfaceTotal combined data usage across all apps using {@code tunIface}
- * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces}
- * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code
- * underlyingIfaces}
- */
- private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface,
- @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal,
- @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
- // Traffic that should be moved off of each underlying interface for tunUid (see
- // deductTrafficFromVpnApp below).
- final Entry[] moved = new Entry[underlyingIfaces.length];
- for (int i = 0; i < underlyingIfaces.length; i++) {
- moved[i] = new Entry();
- }
+ private static Entry tunGetPool(Entry tunIfaceTotal, Entry underlyingIfaceTotal) {
+ Entry pool = new Entry();
+ pool.rxBytes = Math.min(tunIfaceTotal.rxBytes, underlyingIfaceTotal.rxBytes);
+ pool.rxPackets = Math.min(tunIfaceTotal.rxPackets, underlyingIfaceTotal.rxPackets);
+ pool.txBytes = Math.min(tunIfaceTotal.txBytes, underlyingIfaceTotal.txBytes);
+ pool.txPackets = Math.min(tunIfaceTotal.txPackets, underlyingIfaceTotal.txPackets);
+ pool.operations = Math.min(tunIfaceTotal.operations, underlyingIfaceTotal.operations);
+ return pool;
+ }
- final Entry tmpEntry = new Entry();
+ private Entry addTrafficToApplications(int tunUid, String tunIface, String underlyingIface,
+ Entry tunIfaceTotal, Entry pool) {
+ Entry moved = new Entry();
+ Entry tmpEntry = new Entry();
+ tmpEntry.iface = underlyingIface;
for (int i = 0; i < size; i++) {
- if (!Objects.equals(iface[i], tunIface)) {
- // Consider only entries that go onto the VPN interface.
- continue;
- }
- if (uid[i] == tunUid) {
- // Exclude VPN app from the redistribution, as it can choose to create packet
- // streams by writing to itself.
- continue;
- }
- tmpEntry.uid = uid[i];
- tmpEntry.tag = tag[i];
- tmpEntry.metered = metered[i];
- tmpEntry.roaming = roaming[i];
- tmpEntry.defaultNetwork = defaultNetwork[i];
-
- // In a first pass, compute each UID's total share of data across all underlyingIfaces.
- // This is computed on the basis of the share of each UID's usage over tunIface.
- // TODO: Consider refactoring first pass into a separate helper method.
- long totalRxBytes = 0;
- if (tunIfaceTotal.rxBytes > 0) {
- // Note - The multiplication below should not overflow since NetworkStatsService
- // processes this every time device has transmitted/received amount equivalent to
- // global threshold alert (~ 2MB) across all interfaces.
- final long rxBytesAcrossUnderlyingIfaces =
- underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes;
- // app must not be blamed for more than it consumed on tunIface
- totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces);
- }
- long totalRxPackets = 0;
- if (tunIfaceTotal.rxPackets > 0) {
- final long rxPacketsAcrossUnderlyingIfaces =
- underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets;
- totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces);
- }
- long totalTxBytes = 0;
- if (tunIfaceTotal.txBytes > 0) {
- final long txBytesAcrossUnderlyingIfaces =
- underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes;
- totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces);
- }
- long totalTxPackets = 0;
- if (tunIfaceTotal.txPackets > 0) {
- final long txPacketsAcrossUnderlyingIfaces =
- underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets;
- totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces);
- }
- long totalOperations = 0;
- if (tunIfaceTotal.operations > 0) {
- final long operationsAcrossUnderlyingIfaces =
- underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations;
- totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces);
- }
- // In a second pass, distribute these values across interfaces in the proportion that
- // each interface represents of the total traffic of the underlying interfaces.
- for (int j = 0; j < underlyingIfaces.length; j++) {
- tmpEntry.iface = underlyingIfaces[j];
- tmpEntry.rxBytes = 0;
- // Reset 'set' to correct value since it gets updated when adding debug info below.
- tmpEntry.set = set[i];
- if (underlyingIfacesTotal.rxBytes > 0) {
- tmpEntry.rxBytes =
- totalRxBytes
- * perInterfaceTotal[j].rxBytes
- / underlyingIfacesTotal.rxBytes;
+ // the vpn app is excluded from the redistribution but all moved traffic will be
+ // deducted from the vpn app (see deductTrafficFromVpnApp below).
+ if (Objects.equals(iface[i], tunIface) && uid[i] != tunUid) {
+ if (tunIfaceTotal.rxBytes > 0) {
+ tmpEntry.rxBytes = pool.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes;
+ } else {
+ tmpEntry.rxBytes = 0;
}
- tmpEntry.rxPackets = 0;
- if (underlyingIfacesTotal.rxPackets > 0) {
- tmpEntry.rxPackets =
- totalRxPackets
- * perInterfaceTotal[j].rxPackets
- / underlyingIfacesTotal.rxPackets;
+ if (tunIfaceTotal.rxPackets > 0) {
+ tmpEntry.rxPackets = pool.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets;
+ } else {
+ tmpEntry.rxPackets = 0;
}
- tmpEntry.txBytes = 0;
- if (underlyingIfacesTotal.txBytes > 0) {
- tmpEntry.txBytes =
- totalTxBytes
- * perInterfaceTotal[j].txBytes
- / underlyingIfacesTotal.txBytes;
+ if (tunIfaceTotal.txBytes > 0) {
+ tmpEntry.txBytes = pool.txBytes * txBytes[i] / tunIfaceTotal.txBytes;
+ } else {
+ tmpEntry.txBytes = 0;
}
- tmpEntry.txPackets = 0;
- if (underlyingIfacesTotal.txPackets > 0) {
- tmpEntry.txPackets =
- totalTxPackets
- * perInterfaceTotal[j].txPackets
- / underlyingIfacesTotal.txPackets;
+ if (tunIfaceTotal.txPackets > 0) {
+ tmpEntry.txPackets = pool.txPackets * txPackets[i] / tunIfaceTotal.txPackets;
+ } else {
+ tmpEntry.txPackets = 0;
}
- tmpEntry.operations = 0;
- if (underlyingIfacesTotal.operations > 0) {
+ if (tunIfaceTotal.operations > 0) {
tmpEntry.operations =
- totalOperations
- * perInterfaceTotal[j].operations
- / underlyingIfacesTotal.operations;
+ pool.operations * operations[i] / tunIfaceTotal.operations;
+ } else {
+ tmpEntry.operations = 0;
}
-
+ tmpEntry.uid = uid[i];
+ tmpEntry.tag = tag[i];
+ tmpEntry.set = set[i];
+ tmpEntry.metered = metered[i];
+ tmpEntry.roaming = roaming[i];
+ tmpEntry.defaultNetwork = defaultNetwork[i];
combineValues(tmpEntry);
if (tag[i] == TAG_NONE) {
- moved[j].add(tmpEntry);
+ moved.add(tmpEntry);
// Add debug info
tmpEntry.set = SET_DBG_VPN_IN;
combineValues(tmpEntry);
@@ -1407,45 +1311,38 @@
return moved;
}
- private void deductTrafficFromVpnApp(
- int tunUid,
- @NonNull String[] underlyingIfaces,
- @NonNull Entry[] moved) {
- for (int i = 0; i < underlyingIfaces.length; i++) {
- // Add debug info
- moved[i].uid = tunUid;
- moved[i].set = SET_DBG_VPN_OUT;
- moved[i].tag = TAG_NONE;
- moved[i].iface = underlyingIfaces[i];
- moved[i].metered = METERED_ALL;
- moved[i].roaming = ROAMING_ALL;
- moved[i].defaultNetwork = DEFAULT_NETWORK_ALL;
- combineValues(moved[i]);
+ private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) {
+ // Add debug info
+ moved.uid = tunUid;
+ moved.set = SET_DBG_VPN_OUT;
+ moved.tag = TAG_NONE;
+ moved.iface = underlyingIface;
+ moved.metered = METERED_ALL;
+ moved.roaming = ROAMING_ALL;
+ moved.defaultNetwork = DEFAULT_NETWORK_ALL;
+ combineValues(moved);
- // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
- // the TAG_NONE traffic.
- //
- // Relies on the fact that the underlying traffic only has state ROAMING_NO and
- // METERED_NO, which should be the case as it comes directly from the /proc file.
- // We only blend in the roaming data after applying these adjustments, by checking the
- // NetworkIdentity of the underlying iface.
- final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT,
- TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
- if (idxVpnBackground != -1) {
- // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed
- // from foreground usage.
- tunSubtract(idxVpnBackground, this, moved[i]);
- }
+ // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
+ // the TAG_NONE traffic.
+ //
+ // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO,
+ // which should be the case as it comes directly from the /proc file. We only blend in the
+ // roaming data after applying these adjustments, by checking the NetworkIdentity of the
+ // underlying iface.
+ int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
+ if (idxVpnBackground != -1) {
+ tunSubtract(idxVpnBackground, this, moved);
+ }
- final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND,
- TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
- if (idxVpnForeground != -1) {
- tunSubtract(idxVpnForeground, this, moved[i]);
- }
+ int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
+ if (idxVpnForeground != -1) {
+ tunSubtract(idxVpnForeground, this, moved);
}
}
- private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) {
+ private static void tunSubtract(int i, NetworkStats left, Entry right) {
long rxBytes = Math.min(left.rxBytes[i], right.rxBytes);
left.rxBytes[i] -= rxBytes;
right.rxBytes -= rxBytes;
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index d53e032..f61260e 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -719,7 +719,7 @@
}
@UnsupportedAppUsage
- public static final Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() {
+ public static final @android.annotation.NonNull Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() {
@Override
public NetworkStatsHistory createFromParcel(Parcel in) {
return new NetworkStatsHistory(in);
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 60ae352..ae421a4 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -495,7 +495,7 @@
}
@UnsupportedAppUsage
- public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
+ public static final @android.annotation.NonNull Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
@Override
public NetworkTemplate createFromParcel(Parcel in) {
return new NetworkTemplate(in);
diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java
index 9ba17ed..459b140 100644
--- a/core/java/android/net/nsd/NsdServiceInfo.java
+++ b/core/java/android/net/nsd/NsdServiceInfo.java
@@ -355,7 +355,7 @@
}
/** Implement the Parcelable interface */
- public static final Creator<NsdServiceInfo> CREATOR =
+ public static final @android.annotation.NonNull Creator<NsdServiceInfo> CREATOR =
new Creator<NsdServiceInfo>() {
public NsdServiceInfo createFromParcel(Parcel in) {
NsdServiceInfo info = new NsdServiceInfo();
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index c1f5255..b413d8f 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -1369,7 +1369,7 @@
public synchronized IpSecTunnelInterfaceResponse createTunnelInterface(
String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder,
String callingPackage) {
- enforceTunnelPermissions(callingPackage);
+ enforceTunnelFeatureAndPermissions(callingPackage);
checkNotNull(binder, "Null Binder passed to createTunnelInterface");
checkNotNull(underlyingNetwork, "No underlying network was specified");
checkInetAddress(localAddr);
@@ -1455,7 +1455,7 @@
@Override
public synchronized void addAddressToTunnelInterface(
int tunnelResourceId, LinkAddress localAddr, String callingPackage) {
- enforceTunnelPermissions(callingPackage);
+ enforceTunnelFeatureAndPermissions(callingPackage);
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
// Get tunnelInterface record; if no such interface is found, will throw
@@ -1484,7 +1484,7 @@
@Override
public synchronized void removeAddressFromTunnelInterface(
int tunnelResourceId, LinkAddress localAddr, String callingPackage) {
- enforceTunnelPermissions(callingPackage);
+ enforceTunnelFeatureAndPermissions(callingPackage);
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
// Get tunnelInterface record; if no such interface is found, will throw
@@ -1513,7 +1513,7 @@
@Override
public synchronized void deleteTunnelInterface(
int resourceId, String callingPackage) throws RemoteException {
- enforceTunnelPermissions(callingPackage);
+ enforceTunnelFeatureAndPermissions(callingPackage);
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
releaseResource(userRecord.mTunnelInterfaceRecords, resourceId);
}
@@ -1642,7 +1642,12 @@
private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS;
- private void enforceTunnelPermissions(String callingPackage) {
+ private void enforceTunnelFeatureAndPermissions(String callingPackage) {
+ if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) {
+ throw new UnsupportedOperationException(
+ "IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS");
+ }
+
checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels");
switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
case AppOpsManager.MODE_DEFAULT:
@@ -1714,7 +1719,7 @@
IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException {
checkNotNull(c);
if (c.getMode() == IpSecTransform.MODE_TUNNEL) {
- enforceTunnelPermissions(callingPackage);
+ enforceTunnelFeatureAndPermissions(callingPackage);
}
checkIpSecConfig(c);
checkNotNull(binder, "Null Binder passed to createTransform");
@@ -1822,7 +1827,7 @@
public synchronized void applyTunnelModeTransform(
int tunnelResourceId, int direction,
int transformResourceId, String callingPackage) throws RemoteException {
- enforceTunnelPermissions(callingPackage);
+ enforceTunnelFeatureAndPermissions(callingPackage);
checkDirection(direction);
int callingUid = Binder.getCallingUid();
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 2e64965..69efd02 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -263,11 +263,6 @@
return stats;
}
- /**
- * @deprecated Use NetworkStatsService#getDetailedUidStats which also accounts for
- * VPN traffic
- */
- @Deprecated
public NetworkStats readNetworkStatsDetail() throws IOException {
return readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index bdff500..a2e7e0c 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -41,10 +41,10 @@
import com.android.internal.util.FileRotator;
import com.android.internal.util.IndentingPrintWriter;
-import com.google.android.collect.Sets;
-
import libcore.io.IoUtils;
+import com.google.android.collect.Sets;
+
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
@@ -234,7 +234,7 @@
if (vpnArray != null) {
for (VpnInfo info : vpnArray) {
- delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces);
+ delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface);
}
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 484efd6..f34ace5 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -105,6 +105,7 @@
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.INetworkManagementService;
+import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
@@ -292,22 +293,6 @@
/** Data layer operation counters for splicing into other structures. */
private NetworkStats mUidOperations = new NetworkStats(0L, 10);
- /**
- * Snapshot containing most recent network stats for all UIDs across all interfaces and tags
- * since boot.
- *
- * <p>Maintains migrated VPN stats which are result of performing TUN migration on {@link
- * #mLastUidDetailSnapshot}.
- */
- @GuardedBy("mStatsLock")
- private NetworkStats mTunAdjustedStats;
- /**
- * Used by {@link #mTunAdjustedStats} to migrate VPN traffic over delta between this snapshot
- * and latest snapshot.
- */
- @GuardedBy("mStatsLock")
- private NetworkStats mLastUidDetailSnapshot;
-
/** Must be set in factory by calling #setHandler. */
private Handler mHandler;
private Handler.Callback mHandlerCallback;
@@ -341,6 +326,12 @@
Clock.systemUTC());
}
+ private static final class NetworkStatsHandler extends Handler {
+ NetworkStatsHandler(Looper looper, Handler.Callback callback) {
+ super(looper, callback);
+ }
+ }
+
public static NetworkStatsService create(Context context,
INetworkManagementService networkManager) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
@@ -357,7 +348,7 @@
HandlerThread handlerThread = new HandlerThread(TAG);
Handler.Callback callback = new HandlerCallback(service);
handlerThread.start();
- Handler handler = new Handler(handlerThread.getLooper(), callback);
+ Handler handler = new NetworkStatsHandler(handlerThread.getLooper(), callback);
service.setHandler(handler, callback);
return service;
}
@@ -821,39 +812,15 @@
@Override
public NetworkStats getDetailedUidStats(String[] requiredIfaces) {
try {
- // Get the latest snapshot from NetworkStatsFactory.
- // TODO: Querying for INTERFACES_ALL may incur performance penalty. Consider restricting
- // this to limited set of ifaces.
- NetworkStats uidDetailStats = getNetworkStatsUidDetail(INTERFACES_ALL);
-
- // Migrate traffic from VPN UID over delta and update mTunAdjustedStats.
- NetworkStats result;
- synchronized (mStatsLock) {
- migrateTunTraffic(uidDetailStats, mVpnInfos);
- result = mTunAdjustedStats.clone();
- }
-
- // Apply filter based on ifacesToQuery.
final String[] ifacesToQuery =
NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces);
- result.filter(UID_ALL, ifacesToQuery, TAG_ALL);
- return result;
+ return getNetworkStatsUidDetail(ifacesToQuery);
} catch (RemoteException e) {
Log.wtf(TAG, "Error compiling UID stats", e);
return new NetworkStats(0L, 0);
}
}
- @VisibleForTesting
- NetworkStats getTunAdjustedStats() {
- synchronized (mStatsLock) {
- if (mTunAdjustedStats == null) {
- return null;
- }
- return mTunAdjustedStats.clone();
- }
- }
-
@Override
public String[] getMobileIfaces() {
return mMobileIfaces;
@@ -1328,34 +1295,6 @@
// a race condition between the service handler thread and the observer's
mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces),
new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime);
-
- migrateTunTraffic(uidSnapshot, vpnArray);
- }
-
- /**
- * Updates {@link #mTunAdjustedStats} with the delta containing traffic migrated off of VPNs.
- */
- @GuardedBy("mStatsLock")
- private void migrateTunTraffic(NetworkStats uidDetailStats, VpnInfo[] vpnInfoArray) {
- if (mTunAdjustedStats == null) {
- // Either device booted or system server restarted, hence traffic cannot be migrated
- // correctly without knowing the past state of VPN's underlying networks.
- mTunAdjustedStats = uidDetailStats;
- mLastUidDetailSnapshot = uidDetailStats;
- return;
- }
- // Migrate delta traffic from VPN to other apps.
- NetworkStats delta = uidDetailStats.subtract(mLastUidDetailSnapshot);
- for (VpnInfo info : vpnInfoArray) {
- delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces);
- }
- // Filter out debug entries as that may lead to over counting.
- delta.filterDebugEntries();
- // Update #mTunAdjustedStats with migrated delta.
- mTunAdjustedStats.combineAllValues(delta);
- mTunAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime());
- // Update last snapshot.
- mLastUidDetailSnapshot = uidDetailStats;
}
/**