diff --git a/api/current.txt b/api/current.txt index c2645219f1512..1ff9ca9845000 100644 --- a/api/current.txt +++ b/api/current.txt @@ -24497,6 +24497,7 @@ package android.net { public class TrafficStats { ctor public TrafficStats(); method public static void clearThreadStatsTag(); + method public static int getAndSetThreadStatsTag(int); method public static long getMobileRxBytes(); method public static long getMobileRxPackets(); method public static long getMobileTxBytes(); @@ -30078,6 +30079,7 @@ package android.os { method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects(); + method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeath(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure(); diff --git a/api/system-current.txt b/api/system-current.txt index f08cf229ec621..348e8bb43d731 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -26484,6 +26484,7 @@ package android.net { ctor public TrafficStats(); method public static void clearThreadStatsTag(); method public static void clearThreadStatsUid(); + method public static int getAndSetThreadStatsTag(int); method public static long getMobileRxBytes(); method public static long getMobileRxPackets(); method public static long getMobileTxBytes(); @@ -32730,6 +32731,7 @@ package android.os { method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects(); + method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeath(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure(); diff --git a/api/test-current.txt b/api/test-current.txt index e672ededc2f30..b02678886974a 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -24587,6 +24587,7 @@ package android.net { public class TrafficStats { ctor public TrafficStats(); method public static void clearThreadStatsTag(); + method public static int getAndSetThreadStatsTag(int); method public static long getMobileRxBytes(); method public static long getMobileRxPackets(); method public static long getMobileTxBytes(); @@ -30190,6 +30191,7 @@ package android.os { method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects(); + method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeath(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure(); diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java index cea56b53d7637..ffc735c93aef1 100644 --- a/core/java/android/net/SntpClient.java +++ b/core/java/android/net/SntpClient.java @@ -96,6 +96,7 @@ public class SntpClient { public boolean requestTime(InetAddress address, int port, int timeout) { DatagramSocket socket = null; + final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NTP); try { socket = new DatagramSocket(); socket.setSoTimeout(timeout); @@ -161,6 +162,7 @@ public class SntpClient { if (socket != null) { socket.close(); } + TrafficStats.setThreadStatsTag(oldTag); } return true; diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index e7436be273a33..fc66395bcd001 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -166,6 +166,24 @@ public class TrafficStats { NetworkManagementSocketTagger.setThreadSocketStatsTag(tag); } + /** + * Set active tag to use when accounting {@link Socket} traffic originating + * from the current thread. Only one active tag per thread is supported. + *
+ * Changes only take effect during subsequent calls to + * {@link #tagSocket(Socket)}. + *
+ * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and + * used internally by system services like {@link DownloadManager} when + * performing traffic on behalf of an application. + * + * @return the current tag for the calling thread, which can be used to + * restore any existing values after a nested operation is finished + */ + public static int getAndSetThreadStatsTag(int tag) { + return NetworkManagementSocketTagger.setThreadSocketStatsTag(tag); + } + /** * Set active tag to use when accounting {@link Socket} traffic originating * from the current thread. The tag used internally is well-defined to diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 0da4bd16c6976..ae981b77ca841 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -24,6 +24,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.net.TrafficStats; import android.net.Uri; import android.util.ArrayMap; import android.util.Log; @@ -245,11 +246,17 @@ public final class StrictMode { */ private static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8; // for VmPolicy + /** + * @hide + */ + private static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy + private static final int ALL_VM_DETECT_BITS = DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS | DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE | - DETECT_VM_CLEARTEXT_NETWORK | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION; + DETECT_VM_CLEARTEXT_NETWORK | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION | + DETECT_VM_UNTAGGED_SOCKET; // Byte 3: Penalty @@ -300,6 +307,8 @@ public final class StrictMode { */ public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24; + // CAUTION: we started stealing the top bits of Byte 4 for VM above + /** * Mask of all the penalty bits valid for thread policies. */ @@ -715,7 +724,8 @@ public final class StrictMode { public Builder detectAll() { int flags = DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS - | DETECT_VM_FILE_URI_EXPOSURE | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION; + | DETECT_VM_FILE_URI_EXPOSURE | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION + | DETECT_VM_UNTAGGED_SOCKET; // TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have facility // for apps to mark sockets that should be ignored @@ -819,6 +829,22 @@ public final class StrictMode { return enable(DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION); } + /** + * Detect any sockets in the calling app which have not been tagged + * using {@link TrafficStats}. Tagging sockets can help you + * investigate network usage inside your app, such as a narrowing + * down heavy usage to a specific library or component. + *
+ * This currently does not detect sockets created in native code.
+ *
+ * @see TrafficStats#setThreadStatsTag(int)
+ * @see TrafficStats#tagSocket(java.net.Socket)
+ * @see TrafficStats#tagDatagramSocket(java.net.DatagramSocket)
+ */
+ public Builder detectUntaggedSockets() {
+ return enable(DETECT_VM_UNTAGGED_SOCKET);
+ }
+
/**
* Crashes the whole process on violation. This penalty runs at the
* end of all enabled penalties so you'll still get your logging or
@@ -1152,6 +1178,11 @@ public final class StrictMode {
if (IS_ENG_BUILD) {
policyBuilder.penaltyLog();
}
+ // All core system components need to tag their sockets to aid
+ // system health investigations
+ if (android.os.Process.myUid() < android.os.Process.FIRST_APPLICATION_UID) {
+ policyBuilder.detectUntaggedSockets();
+ }
setVmPolicy(policyBuilder.build());
setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
}
@@ -1829,6 +1860,13 @@ public final class StrictMode {
return (sVmPolicyMask & DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION) != 0;
}
+ /**
+ * @hide
+ */
+ public static boolean vmUntaggedSocketEnabled() {
+ return (sVmPolicyMask & DETECT_VM_UNTAGGED_SOCKET) != 0;
+ }
+
/**
* @hide
*/
@@ -1911,6 +1949,14 @@ public final class StrictMode {
forceDeath);
}
+ /**
+ * @hide
+ */
+ public static void onUntaggedSocket() {
+ onVmPolicyViolation(null, new Throwable("Untagged socket detected; use"
+ + " TrafficStats.setThreadSocketTag() to track all network usage"));
+ }
+
// Map from VM violation fingerprint to uptime millis.
private static final HashMap