Restrict TrafficStats due to privacy concerns.

Granular per-UID network statistics can be used to infer user
behavior over time, so they fall under the umbrella of the
PACKAGE_USAGE_STATS permission.

Since we can't check app-ops based permissions in the kernel, the
best we can do is redirect users to the NetworkStatsManager class,
which offers a much more robust historical data set.

Bug: 27577101
Change-Id: I696bdc5e0b3d7e24acf35f388d0ab13617ed8af3
This commit is contained in:
Jeff Sharkey
2016-03-09 16:40:15 -07:00
parent 9f5c3b8c68
commit 27c8a07be6

View File

@@ -19,6 +19,7 @@ package android.net;
import android.annotation.SystemApi; import android.annotation.SystemApi;
import android.app.DownloadManager; import android.app.DownloadManager;
import android.app.backup.BackupManager; import android.app.backup.BackupManager;
import android.app.usage.NetworkStatsManager;
import android.content.Context; import android.content.Context;
import android.media.MediaPlayer; import android.media.MediaPlayer;
import android.os.RemoteException; import android.os.RemoteException;
@@ -37,8 +38,12 @@ import java.net.SocketException;
* bytes transmitted and received and network packets transmitted and received, * bytes transmitted and received and network packets transmitted and received,
* over all interfaces, over the mobile interface, and on a per-UID basis. * over all interfaces, over the mobile interface, and on a per-UID basis.
* <p> * <p>
* These statistics may not be available on all platforms. If the statistics * These statistics may not be available on all platforms. If the statistics are
* are not supported by this device, {@link #UNSUPPORTED} will be returned. * not supported by this device, {@link #UNSUPPORTED} will be returned.
* <p>
* Note that the statistics returned by this class reset and start from zero
* after every reboot. To access more robust historical network statistics data,
* use {@link NetworkStatsManager} instead.
*/ */
public class TrafficStats { public class TrafficStats {
/** /**
@@ -497,14 +502,27 @@ public class TrafficStats {
* monotonically since device boot. Statistics are measured at the network * monotonically since device boot. Statistics are measured at the network
* layer, so they include both TCP and UDP usage. * layer, so they include both TCP and UDP usage.
* <p> * <p>
* Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
* {@link #UNSUPPORTED} on devices where statistics aren't available. * return {@link #UNSUPPORTED} on devices where statistics aren't available.
* <p>
* Starting in {@link android.os.Build.VERSION_CODES#N} this will only
* report traffic statistics for the calling UID. It will return
* {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
* historical network statistics belonging to other UIDs, use
* {@link NetworkStatsManager}.
* *
* @see android.os.Process#myUid() * @see android.os.Process#myUid()
* @see android.content.pm.ApplicationInfo#uid * @see android.content.pm.ApplicationInfo#uid
*/ */
public static long getUidTxBytes(int uid) { public static long getUidTxBytes(int uid) {
// This isn't actually enforcing any security; it just returns the
// unsupported value. The real filtering is done at the kernel level.
final int callingUid = android.os.Process.myUid();
if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
return nativeGetUidStat(uid, TYPE_TX_BYTES); return nativeGetUidStat(uid, TYPE_TX_BYTES);
} else {
return UNSUPPORTED;
}
} }
/** /**
@@ -515,12 +533,25 @@ public class TrafficStats {
* <p> * <p>
* Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
* {@link #UNSUPPORTED} on devices where statistics aren't available. * {@link #UNSUPPORTED} on devices where statistics aren't available.
* <p>
* Starting in {@link android.os.Build.VERSION_CODES#N} this will only
* report traffic statistics for the calling UID. It will return
* {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
* historical network statistics belonging to other UIDs, use
* {@link NetworkStatsManager}.
* *
* @see android.os.Process#myUid() * @see android.os.Process#myUid()
* @see android.content.pm.ApplicationInfo#uid * @see android.content.pm.ApplicationInfo#uid
*/ */
public static long getUidRxBytes(int uid) { public static long getUidRxBytes(int uid) {
// This isn't actually enforcing any security; it just returns the
// unsupported value. The real filtering is done at the kernel level.
final int callingUid = android.os.Process.myUid();
if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
return nativeGetUidStat(uid, TYPE_RX_BYTES); return nativeGetUidStat(uid, TYPE_RX_BYTES);
} else {
return UNSUPPORTED;
}
} }
/** /**
@@ -531,12 +562,25 @@ public class TrafficStats {
* <p> * <p>
* Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
* {@link #UNSUPPORTED} on devices where statistics aren't available. * {@link #UNSUPPORTED} on devices where statistics aren't available.
* <p>
* Starting in {@link android.os.Build.VERSION_CODES#N} this will only
* report traffic statistics for the calling UID. It will return
* {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
* historical network statistics belonging to other UIDs, use
* {@link NetworkStatsManager}.
* *
* @see android.os.Process#myUid() * @see android.os.Process#myUid()
* @see android.content.pm.ApplicationInfo#uid * @see android.content.pm.ApplicationInfo#uid
*/ */
public static long getUidTxPackets(int uid) { public static long getUidTxPackets(int uid) {
// This isn't actually enforcing any security; it just returns the
// unsupported value. The real filtering is done at the kernel level.
final int callingUid = android.os.Process.myUid();
if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
return nativeGetUidStat(uid, TYPE_TX_PACKETS); return nativeGetUidStat(uid, TYPE_TX_PACKETS);
} else {
return UNSUPPORTED;
}
} }
/** /**
@@ -547,12 +591,25 @@ public class TrafficStats {
* <p> * <p>
* Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
* {@link #UNSUPPORTED} on devices where statistics aren't available. * {@link #UNSUPPORTED} on devices where statistics aren't available.
* <p>
* Starting in {@link android.os.Build.VERSION_CODES#N} this will only
* report traffic statistics for the calling UID. It will return
* {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
* historical network statistics belonging to other UIDs, use
* {@link NetworkStatsManager}.
* *
* @see android.os.Process#myUid() * @see android.os.Process#myUid()
* @see android.content.pm.ApplicationInfo#uid * @see android.content.pm.ApplicationInfo#uid
*/ */
public static long getUidRxPackets(int uid) { public static long getUidRxPackets(int uid) {
// This isn't actually enforcing any security; it just returns the
// unsupported value. The real filtering is done at the kernel level.
final int callingUid = android.os.Process.myUid();
if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
return nativeGetUidStat(uid, TYPE_RX_PACKETS); return nativeGetUidStat(uid, TYPE_RX_PACKETS);
} else {
return UNSUPPORTED;
}
} }
/** /**