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#ROAMING_ALL}.
|
||||
* <p />
|
||||
* <b>NOTE:</b> Accessing stats for apps other than the calling app requires the permission
|
||||
* {@link android.Manifest.permission#PACKAGE_USAGE_STATS}, which is a system-level permission and
|
||||
* will not be granted to third-party apps. However, declaring the permission implies intention to
|
||||
* use the API and the user of the device can grant permission through the Settings application.
|
||||
* <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
|
||||
* calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
|
||||
* which is a system-level permission and will not be granted to third-party apps. However,
|
||||
* 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
|
||||
* (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.
|
||||
|
||||
@@ -66,14 +66,25 @@ public final class NetworkStatsAccess {
|
||||
*
|
||||
* <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.
|
||||
* <li>Profile owners.
|
||||
* </ul>
|
||||
*/
|
||||
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
|
||||
* running on other users/profiles.
|
||||
@@ -85,7 +96,7 @@ public final class NetworkStatsAccess {
|
||||
* <li>The system UID.
|
||||
* </ul>
|
||||
*/
|
||||
int DEVICE = 2;
|
||||
int DEVICE = 3;
|
||||
}
|
||||
|
||||
/** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
|
||||
@@ -107,11 +118,15 @@ public final class NetworkStatsAccess {
|
||||
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,
|
||||
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
|
||||
if (hasAppOpsPermission(context, callingUid, callingPackage) || isProfileOwner
|
||||
|| context.checkCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY) ==
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
if (isProfileOwner) {
|
||||
// Apps with the AppOps permission, profile owners, and apps with the privileged
|
||||
// permission can access data usage for all apps in this user/profile.
|
||||
return NetworkStatsAccess.Level.USER;
|
||||
@@ -131,6 +146,7 @@ public final class NetworkStatsAccess {
|
||||
case NetworkStatsAccess.Level.DEVICE:
|
||||
// Device-level access - can access usage for any uid.
|
||||
return true;
|
||||
case NetworkStatsAccess.Level.DEVICESUMMARY:
|
||||
case NetworkStatsAccess.Level.USER:
|
||||
// User-level access - can access usage for any app running in the same user, along
|
||||
// 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,
|
||||
long end) {
|
||||
@NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
|
||||
if (accessLevel < NetworkStatsAccess.Level.DEVICE) {
|
||||
if (accessLevel < NetworkStatsAccess.Level.DEVICESUMMARY) {
|
||||
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);
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
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(
|
||||
internalGetSummaryForNetwork(template, start, end, accessLevel));
|
||||
internalGetSummaryForNetwork(template, start, end,
|
||||
NetworkStatsAccess.Level.DEVICE));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user