Introduce DEVICESUMMARY access level to NetworkStatsAccess.
Apps with PACKAGE_USAGE_STATS app op or READ_NETWORK_USAGE_HISTORY granted can query the summarized device data usage (but not individual uids running in other users or profiles). Bug:26677052 Change-Id: Id51631638f338a8cf48172c9b41746228a335084
This commit is contained in:
@@ -52,10 +52,12 @@ import android.util.Log;
|
|||||||
* {@link NetworkStats.Bucket#STATE_ALL} and all Bucket's roaming is going to be
|
* {@link NetworkStats.Bucket#STATE_ALL} and all Bucket's roaming is going to be
|
||||||
* {@link NetworkStats.Bucket#ROAMING_ALL}.
|
* {@link NetworkStats.Bucket#ROAMING_ALL}.
|
||||||
* <p />
|
* <p />
|
||||||
* <b>NOTE:</b> Accessing stats for apps other than the calling app requires the permission
|
* <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
|
||||||
* {@link android.Manifest.permission#PACKAGE_USAGE_STATS}, which is a system-level permission and
|
* calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
|
||||||
* will not be granted to third-party apps. However, declaring the permission implies intention to
|
* which is a system-level permission and will not be granted to third-party apps. However,
|
||||||
* use the API and the user of the device can grant permission through the Settings application.
|
* declaring the permission implies intention to use the API and the user of the device can grant
|
||||||
|
* permission through the Settings application.
|
||||||
|
* <p />
|
||||||
* Profile owner apps are automatically granted permission to query data on the profile they manage
|
* Profile owner apps are automatically granted permission to query data on the profile they manage
|
||||||
* (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
|
* (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
|
||||||
* privileged apps likewise get access to usage data for all users on the device.
|
* privileged apps likewise get access to usage data for all users on the device.
|
||||||
|
|||||||
@@ -66,14 +66,25 @@ public final class NetworkStatsAccess {
|
|||||||
*
|
*
|
||||||
* <p>Granted to:
|
* <p>Granted to:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Apps with the PACKAGE_USAGE_STATS permission granted. Note that this is an AppOps bit
|
|
||||||
* so it is not necessarily sufficient to declare this in the manifest.
|
|
||||||
* <li>Apps with the (signature/privileged) READ_NETWORK_USAGE_HISTORY permission.
|
|
||||||
* <li>Profile owners.
|
* <li>Profile owners.
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
int USER = 1;
|
int USER = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access level for apps which can access usage summary of device. Device summary includes
|
||||||
|
* usage by apps running in any profiles/users, however this access level does not
|
||||||
|
* allow querying usage of individual apps running in other profiles/users.
|
||||||
|
*
|
||||||
|
* <p>Granted to:
|
||||||
|
* <ul>
|
||||||
|
* <li>Apps with the PACKAGE_USAGE_STATS permission granted. Note that this is an AppOps bit
|
||||||
|
* so it is not necessarily sufficient to declare this in the manifest.
|
||||||
|
* <li>Apps with the (signature/privileged) READ_NETWORK_USAGE_HISTORY permission.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
int DEVICESUMMARY = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access level for apps which can access usage for any app on the device, including apps
|
* Access level for apps which can access usage for any app on the device, including apps
|
||||||
* running on other users/profiles.
|
* running on other users/profiles.
|
||||||
@@ -85,7 +96,7 @@ public final class NetworkStatsAccess {
|
|||||||
* <li>The system UID.
|
* <li>The system UID.
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
int DEVICE = 2;
|
int DEVICE = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
|
/** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
|
||||||
@@ -107,11 +118,15 @@ public final class NetworkStatsAccess {
|
|||||||
return NetworkStatsAccess.Level.DEVICE;
|
return NetworkStatsAccess.Level.DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean hasAppOpsPermission = hasAppOpsPermission(context, callingUid, callingPackage);
|
||||||
|
if (hasAppOpsPermission || context.checkCallingOrSelfPermission(
|
||||||
|
READ_NETWORK_USAGE_HISTORY) == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
return NetworkStatsAccess.Level.DEVICESUMMARY;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isProfileOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
|
boolean isProfileOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
|
||||||
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
|
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
|
||||||
if (hasAppOpsPermission(context, callingUid, callingPackage) || isProfileOwner
|
if (isProfileOwner) {
|
||||||
|| context.checkCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY) ==
|
|
||||||
PackageManager.PERMISSION_GRANTED) {
|
|
||||||
// Apps with the AppOps permission, profile owners, and apps with the privileged
|
// Apps with the AppOps permission, profile owners, and apps with the privileged
|
||||||
// permission can access data usage for all apps in this user/profile.
|
// permission can access data usage for all apps in this user/profile.
|
||||||
return NetworkStatsAccess.Level.USER;
|
return NetworkStatsAccess.Level.USER;
|
||||||
@@ -131,6 +146,7 @@ public final class NetworkStatsAccess {
|
|||||||
case NetworkStatsAccess.Level.DEVICE:
|
case NetworkStatsAccess.Level.DEVICE:
|
||||||
// Device-level access - can access usage for any uid.
|
// Device-level access - can access usage for any uid.
|
||||||
return true;
|
return true;
|
||||||
|
case NetworkStatsAccess.Level.DEVICESUMMARY:
|
||||||
case NetworkStatsAccess.Level.USER:
|
case NetworkStatsAccess.Level.USER:
|
||||||
// User-level access - can access usage for any app running in the same user, along
|
// User-level access - can access usage for any app running in the same user, along
|
||||||
// with some special uids (system, removed, or tethering).
|
// with some special uids (system, removed, or tethering).
|
||||||
|
|||||||
@@ -484,15 +484,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
public NetworkStats getDeviceSummaryForNetwork(NetworkTemplate template, long start,
|
public NetworkStats getDeviceSummaryForNetwork(NetworkTemplate template, long start,
|
||||||
long end) {
|
long end) {
|
||||||
@NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
|
@NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
|
||||||
if (accessLevel < NetworkStatsAccess.Level.DEVICE) {
|
if (accessLevel < NetworkStatsAccess.Level.DEVICESUMMARY) {
|
||||||
throw new SecurityException("Calling package " + mCallingPackage
|
throw new SecurityException("Calling package " + mCallingPackage
|
||||||
+ " cannot access device-level network stats");
|
+ " cannot access device summary network stats");
|
||||||
}
|
}
|
||||||
NetworkStats result = new NetworkStats(end - start, 1);
|
NetworkStats result = new NetworkStats(end - start, 1);
|
||||||
final long ident = Binder.clearCallingIdentity();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
|
// Using access level higher than the one we checked for above.
|
||||||
|
// Reason is that we are combining usage data in a way that is not PII
|
||||||
|
// anymore.
|
||||||
result.combineAllValues(
|
result.combineAllValues(
|
||||||
internalGetSummaryForNetwork(template, start, end, accessLevel));
|
internalGetSummaryForNetwork(template, start, end,
|
||||||
|
NetworkStatsAccess.Level.DEVICE));
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user