Merge "[MS41.1] Prepare for APIs for querying usage with template" am: 22c1481659 am: 39f1142822 am: b8e7864780
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1937268 Change-Id: Ie10cd1aedf4b7449356cdba0f64ba6c5d088640b
This commit is contained in:
@@ -556,7 +556,7 @@ public final class NetworkStats implements AutoCloseable {
|
||||
/**
|
||||
* Collects history results for uid and resets history enumeration index.
|
||||
*/
|
||||
void startHistoryEnumeration(int uid, int tag, int state) {
|
||||
void startHistoryUidEnumeration(int uid, int tag, int state) {
|
||||
mHistory = null;
|
||||
try {
|
||||
mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
|
||||
@@ -570,6 +570,20 @@ public final class NetworkStats implements AutoCloseable {
|
||||
mEnumerationIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects history results for network and resets history enumeration index.
|
||||
*/
|
||||
void startHistoryDeviceEnumeration() {
|
||||
try {
|
||||
mHistory = mSession.getHistoryIntervalForNetwork(
|
||||
mTemplate, NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
mHistory = null;
|
||||
}
|
||||
mEnumerationIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts uid enumeration for current user.
|
||||
* @throws RemoteException
|
||||
|
||||
@@ -433,6 +433,42 @@ public class NetworkStatsManager {
|
||||
return null; // To make the compiler happy.
|
||||
}
|
||||
|
||||
/**
|
||||
* Query usage statistics details for networks matching a given {@link NetworkTemplate}.
|
||||
*
|
||||
* Result is not aggregated over time. This means buckets' start and
|
||||
* end timestamps will be between 'startTime' and 'endTime' parameters.
|
||||
* <p>Only includes buckets whose entire time period is included between
|
||||
* startTime and endTime. Doesn't interpolate or return partial buckets.
|
||||
* Since bucket length is in the order of hours, this
|
||||
* method cannot be used to measure data usage on a fine grained time scale.
|
||||
* This may take a long time, and apps should avoid calling this on their main thread.
|
||||
*
|
||||
* @param template Template used to match networks. See {@link NetworkTemplate}.
|
||||
* @param startTime Start of period, in milliseconds since the Unix epoch, see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param endTime End of period, in milliseconds since the Unix epoch, see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @return Statistics which is described above.
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
// @SystemApi(client = MODULE_LIBRARIES)
|
||||
@WorkerThread
|
||||
public NetworkStats queryDetailsForDevice(@NonNull NetworkTemplate template,
|
||||
long startTime, long endTime) {
|
||||
try {
|
||||
final NetworkStats result =
|
||||
new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
|
||||
result.startHistoryDeviceEnumeration();
|
||||
return result;
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
return null; // To make the compiler happy.
|
||||
}
|
||||
|
||||
/**
|
||||
* Query network usage statistics details for a given uid.
|
||||
* This may take a long time, and apps should avoid calling this on their main thread.
|
||||
@@ -499,7 +535,8 @@ public class NetworkStatsManager {
|
||||
* @param endTime End of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param uid UID of app
|
||||
* @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
|
||||
* @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
|
||||
* across all the tags.
|
||||
* @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
|
||||
* traffic from all states.
|
||||
* @return Statistics object or null if an error happened during statistics collection.
|
||||
@@ -514,21 +551,51 @@ public class NetworkStatsManager {
|
||||
return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public NetworkStats queryDetailsForUidTagState(NetworkTemplate template,
|
||||
/**
|
||||
* Query network usage statistics details for a given template, uid, tag, and state.
|
||||
*
|
||||
* Only usable for uids belonging to calling user. Result is not aggregated over time.
|
||||
* This means buckets' start and end timestamps are going to be between 'startTime' and
|
||||
* 'endTime' parameters. The uid is going to be the same as the 'uid' parameter, the tag
|
||||
* the same as the 'tag' parameter, and the state the same as the 'state' parameter.
|
||||
* defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
|
||||
* metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
|
||||
* roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
|
||||
* <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
|
||||
* interpolate across partial buckets. Since bucket length is in the order of hours, this
|
||||
* method cannot be used to measure data usage on a fine grained time scale.
|
||||
* This may take a long time, and apps should avoid calling this on their main thread.
|
||||
*
|
||||
* @param template Template used to match networks. See {@link NetworkTemplate}.
|
||||
* @param startTime Start of period, in milliseconds since the Unix epoch, see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param endTime End of period, in milliseconds since the Unix epoch, see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param uid UID of app
|
||||
* @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
|
||||
* across all the tags.
|
||||
* @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
|
||||
* traffic from all states.
|
||||
* @return Statistics which is described above.
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
// @SystemApi(client = MODULE_LIBRARIES)
|
||||
@WorkerThread
|
||||
public NetworkStats queryDetailsForUidTagState(@NonNull NetworkTemplate template,
|
||||
long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
|
||||
|
||||
NetworkStats result;
|
||||
try {
|
||||
result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
|
||||
result.startHistoryEnumeration(uid, tag, state);
|
||||
final NetworkStats result = new NetworkStats(
|
||||
mContext, template, mFlags, startTime, endTime, mService);
|
||||
result.startHistoryUidEnumeration(uid, tag, state);
|
||||
return result;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
|
||||
+ " state=" + state, e);
|
||||
return null;
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
return result;
|
||||
return null; // To make the compiler happy.
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,6 +32,11 @@ interface INetworkStatsSession {
|
||||
/** Return historical network layer stats for traffic that matches template. */
|
||||
@UnsupportedAppUsage
|
||||
NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
|
||||
/**
|
||||
* Return historical network layer stats for traffic that matches template, start and end
|
||||
* timestamp.
|
||||
*/
|
||||
NetworkStatsHistory getHistoryIntervalForNetwork(in NetworkTemplate template, int fields, long start, long end);
|
||||
|
||||
/**
|
||||
* Return network layer usage summary per UID for traffic that matches template.
|
||||
|
||||
@@ -154,6 +154,7 @@ import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
|
||||
import com.android.net.module.util.BestClock;
|
||||
import com.android.net.module.util.BinderUtils;
|
||||
import com.android.net.module.util.CollectionUtils;
|
||||
import com.android.net.module.util.LocationPermissionChecker;
|
||||
import com.android.net.module.util.NetworkStatsUtils;
|
||||
import com.android.net.module.util.PermissionUtils;
|
||||
|
||||
@@ -365,6 +366,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
@NonNull
|
||||
private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor;
|
||||
|
||||
@NonNull
|
||||
private final LocationPermissionChecker mLocationPermissionChecker;
|
||||
|
||||
private static @NonNull File getDefaultSystemDir() {
|
||||
return new File(Environment.getDataDirectory(), "system");
|
||||
}
|
||||
@@ -461,6 +465,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
mContentResolver = mContext.getContentResolver();
|
||||
mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
|
||||
mNetworkStatsSubscriptionsMonitor);
|
||||
mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -508,6 +513,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @see LocationPermissionChecker
|
||||
*/
|
||||
public LocationPermissionChecker makeLocationPermissionChecker(final Context context) {
|
||||
return new LocationPermissionChecker(context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -773,6 +785,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
@Override
|
||||
public NetworkStats getDeviceSummaryForNetwork(
|
||||
NetworkTemplate template, long start, long end) {
|
||||
enforceTemplatePermissions(template, callingPackage);
|
||||
return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
|
||||
mAccessLevel, mCallingUid);
|
||||
}
|
||||
@@ -780,19 +793,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
@Override
|
||||
public NetworkStats getSummaryForNetwork(
|
||||
NetworkTemplate template, long start, long end) {
|
||||
enforceTemplatePermissions(template, callingPackage);
|
||||
return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
|
||||
mAccessLevel, mCallingUid);
|
||||
}
|
||||
|
||||
// TODO: Remove this after all callers are removed.
|
||||
@Override
|
||||
public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
|
||||
enforceTemplatePermissions(template, callingPackage);
|
||||
return internalGetHistoryForNetwork(template, restrictedFlags, fields,
|
||||
mAccessLevel, mCallingUid);
|
||||
mAccessLevel, mCallingUid, Long.MIN_VALUE, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkStatsHistory getHistoryIntervalForNetwork(NetworkTemplate template,
|
||||
int fields, long start, long end) {
|
||||
enforceTemplatePermissions(template, callingPackage);
|
||||
// TODO(b/200768422): Redact returned history if the template is location
|
||||
// sensitive but the caller is not privileged.
|
||||
return internalGetHistoryForNetwork(template, restrictedFlags, fields,
|
||||
mAccessLevel, mCallingUid, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkStats getSummaryForAllUid(
|
||||
NetworkTemplate template, long start, long end, boolean includeTags) {
|
||||
enforceTemplatePermissions(template, callingPackage);
|
||||
try {
|
||||
final NetworkStats stats = getUidComplete()
|
||||
.getSummary(template, start, end, mAccessLevel, mCallingUid);
|
||||
@@ -810,6 +837,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
@Override
|
||||
public NetworkStats getTaggedSummaryForAllUid(
|
||||
NetworkTemplate template, long start, long end) {
|
||||
enforceTemplatePermissions(template, callingPackage);
|
||||
try {
|
||||
final NetworkStats tagStats = getUidTagComplete()
|
||||
.getSummary(template, start, end, mAccessLevel, mCallingUid);
|
||||
@@ -822,6 +850,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
@Override
|
||||
public NetworkStatsHistory getHistoryForUid(
|
||||
NetworkTemplate template, int uid, int set, int tag, int fields) {
|
||||
enforceTemplatePermissions(template, callingPackage);
|
||||
// NOTE: We don't augment UID-level statistics
|
||||
if (tag == TAG_NONE) {
|
||||
return getUidComplete().getHistory(template, null, uid, set, tag, fields,
|
||||
@@ -836,6 +865,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
public NetworkStatsHistory getHistoryIntervalForUid(
|
||||
NetworkTemplate template, int uid, int set, int tag, int fields,
|
||||
long start, long end) {
|
||||
enforceTemplatePermissions(template, callingPackage);
|
||||
// TODO(b/200768422): Redact returned history if the template is location
|
||||
// sensitive but the caller is not privileged.
|
||||
// NOTE: We don't augment UID-level statistics
|
||||
if (tag == TAG_NONE) {
|
||||
return getUidComplete().getHistory(template, null, uid, set, tag, fields,
|
||||
@@ -857,6 +889,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
};
|
||||
}
|
||||
|
||||
private void enforceTemplatePermissions(@NonNull NetworkTemplate template,
|
||||
@NonNull String callingPackage) {
|
||||
// For a template with wifi network keys, it is possible for a malicious
|
||||
// client to track the user locations via querying data usage. Thus, enforce
|
||||
// fine location permission check.
|
||||
if (!template.getWifiNetworkKeys().isEmpty()) {
|
||||
final boolean canAccessFineLocation = mLocationPermissionChecker
|
||||
.checkCallersLocationPermission(callingPackage,
|
||||
null /* featureId */,
|
||||
Binder.getCallingUid(),
|
||||
false /* coarseForTargetSdkLessThanQ */,
|
||||
null /* message */);
|
||||
if (!canAccessFineLocation) {
|
||||
throw new SecurityException("Access fine location is required when querying"
|
||||
+ " with wifi network keys, make sure the app has the necessary"
|
||||
+ "permissions and the location toggle is on.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
|
||||
return NetworkStatsAccess.checkAccessLevel(
|
||||
mContext, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage);
|
||||
@@ -893,7 +945,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
// We've been using pure XT stats long enough that we no longer need to
|
||||
// splice DEV and XT together.
|
||||
final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL,
|
||||
accessLevel, callingUid);
|
||||
accessLevel, callingUid, start, end);
|
||||
|
||||
final long now = System.currentTimeMillis();
|
||||
final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
|
||||
@@ -910,14 +962,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
* appropriate.
|
||||
*/
|
||||
private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template,
|
||||
int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) {
|
||||
int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid,
|
||||
long start, long end) {
|
||||
// We've been using pure XT stats long enough that we no longer need to
|
||||
// splice DEV and XT together.
|
||||
final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags);
|
||||
synchronized (mStatsLock) {
|
||||
return mXtStatsCached.getHistory(template, augmentPlan,
|
||||
UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE,
|
||||
accessLevel, callingUid);
|
||||
UID_ALL, SET_ALL, TAG_NONE, fields, start, end, accessLevel, callingUid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user