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.
|
* 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;
|
mHistory = null;
|
||||||
try {
|
try {
|
||||||
mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
|
mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
|
||||||
@@ -570,6 +570,20 @@ public final class NetworkStats implements AutoCloseable {
|
|||||||
mEnumerationIndex = 0;
|
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.
|
* Starts uid enumeration for current user.
|
||||||
* @throws RemoteException
|
* @throws RemoteException
|
||||||
|
|||||||
@@ -433,6 +433,42 @@ public class NetworkStatsManager {
|
|||||||
return null; // To make the compiler happy.
|
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.
|
* 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.
|
* 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
|
* @param endTime End of period. Defined in terms of "Unix time", see
|
||||||
* {@link java.lang.System#currentTimeMillis}.
|
* {@link java.lang.System#currentTimeMillis}.
|
||||||
* @param uid UID of app
|
* @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
|
* @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
|
||||||
* traffic from all states.
|
* traffic from all states.
|
||||||
* @return Statistics object or null if an error happened during statistics collection.
|
* @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);
|
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 {
|
long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
|
||||||
|
|
||||||
NetworkStats result;
|
|
||||||
try {
|
try {
|
||||||
result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
|
final NetworkStats result = new NetworkStats(
|
||||||
result.startHistoryEnumeration(uid, tag, state);
|
mContext, template, mFlags, startTime, endTime, mService);
|
||||||
|
result.startHistoryUidEnumeration(uid, tag, state);
|
||||||
|
return result;
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
|
Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
|
||||||
+ " state=" + state, e);
|
+ " 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. */
|
/** Return historical network layer stats for traffic that matches template. */
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
|
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.
|
* 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.BestClock;
|
||||||
import com.android.net.module.util.BinderUtils;
|
import com.android.net.module.util.BinderUtils;
|
||||||
import com.android.net.module.util.CollectionUtils;
|
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.NetworkStatsUtils;
|
||||||
import com.android.net.module.util.PermissionUtils;
|
import com.android.net.module.util.PermissionUtils;
|
||||||
|
|
||||||
@@ -365,6 +366,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
@NonNull
|
@NonNull
|
||||||
private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor;
|
private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private final LocationPermissionChecker mLocationPermissionChecker;
|
||||||
|
|
||||||
private static @NonNull File getDefaultSystemDir() {
|
private static @NonNull File getDefaultSystemDir() {
|
||||||
return new File(Environment.getDataDirectory(), "system");
|
return new File(Environment.getDataDirectory(), "system");
|
||||||
}
|
}
|
||||||
@@ -461,6 +465,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
mContentResolver = mContext.getContentResolver();
|
mContentResolver = mContext.getContentResolver();
|
||||||
mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
|
mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
|
||||||
mNetworkStatsSubscriptionsMonitor);
|
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
|
@Override
|
||||||
public NetworkStats getDeviceSummaryForNetwork(
|
public NetworkStats getDeviceSummaryForNetwork(
|
||||||
NetworkTemplate template, long start, long end) {
|
NetworkTemplate template, long start, long end) {
|
||||||
|
enforceTemplatePermissions(template, callingPackage);
|
||||||
return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
|
return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
|
||||||
mAccessLevel, mCallingUid);
|
mAccessLevel, mCallingUid);
|
||||||
}
|
}
|
||||||
@@ -780,19 +793,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public NetworkStats getSummaryForNetwork(
|
public NetworkStats getSummaryForNetwork(
|
||||||
NetworkTemplate template, long start, long end) {
|
NetworkTemplate template, long start, long end) {
|
||||||
|
enforceTemplatePermissions(template, callingPackage);
|
||||||
return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
|
return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
|
||||||
mAccessLevel, mCallingUid);
|
mAccessLevel, mCallingUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove this after all callers are removed.
|
||||||
@Override
|
@Override
|
||||||
public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
|
public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
|
||||||
|
enforceTemplatePermissions(template, callingPackage);
|
||||||
return internalGetHistoryForNetwork(template, restrictedFlags, fields,
|
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
|
@Override
|
||||||
public NetworkStats getSummaryForAllUid(
|
public NetworkStats getSummaryForAllUid(
|
||||||
NetworkTemplate template, long start, long end, boolean includeTags) {
|
NetworkTemplate template, long start, long end, boolean includeTags) {
|
||||||
|
enforceTemplatePermissions(template, callingPackage);
|
||||||
try {
|
try {
|
||||||
final NetworkStats stats = getUidComplete()
|
final NetworkStats stats = getUidComplete()
|
||||||
.getSummary(template, start, end, mAccessLevel, mCallingUid);
|
.getSummary(template, start, end, mAccessLevel, mCallingUid);
|
||||||
@@ -810,6 +837,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public NetworkStats getTaggedSummaryForAllUid(
|
public NetworkStats getTaggedSummaryForAllUid(
|
||||||
NetworkTemplate template, long start, long end) {
|
NetworkTemplate template, long start, long end) {
|
||||||
|
enforceTemplatePermissions(template, callingPackage);
|
||||||
try {
|
try {
|
||||||
final NetworkStats tagStats = getUidTagComplete()
|
final NetworkStats tagStats = getUidTagComplete()
|
||||||
.getSummary(template, start, end, mAccessLevel, mCallingUid);
|
.getSummary(template, start, end, mAccessLevel, mCallingUid);
|
||||||
@@ -822,6 +850,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public NetworkStatsHistory getHistoryForUid(
|
public NetworkStatsHistory getHistoryForUid(
|
||||||
NetworkTemplate template, int uid, int set, int tag, int fields) {
|
NetworkTemplate template, int uid, int set, int tag, int fields) {
|
||||||
|
enforceTemplatePermissions(template, callingPackage);
|
||||||
// NOTE: We don't augment UID-level statistics
|
// NOTE: We don't augment UID-level statistics
|
||||||
if (tag == TAG_NONE) {
|
if (tag == TAG_NONE) {
|
||||||
return getUidComplete().getHistory(template, null, uid, set, tag, fields,
|
return getUidComplete().getHistory(template, null, uid, set, tag, fields,
|
||||||
@@ -836,6 +865,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
public NetworkStatsHistory getHistoryIntervalForUid(
|
public NetworkStatsHistory getHistoryIntervalForUid(
|
||||||
NetworkTemplate template, int uid, int set, int tag, int fields,
|
NetworkTemplate template, int uid, int set, int tag, int fields,
|
||||||
long start, long end) {
|
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
|
// NOTE: We don't augment UID-level statistics
|
||||||
if (tag == TAG_NONE) {
|
if (tag == TAG_NONE) {
|
||||||
return getUidComplete().getHistory(template, null, uid, set, tag, fields,
|
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) {
|
private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
|
||||||
return NetworkStatsAccess.checkAccessLevel(
|
return NetworkStatsAccess.checkAccessLevel(
|
||||||
mContext, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage);
|
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
|
// We've been using pure XT stats long enough that we no longer need to
|
||||||
// splice DEV and XT together.
|
// splice DEV and XT together.
|
||||||
final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL,
|
final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL,
|
||||||
accessLevel, callingUid);
|
accessLevel, callingUid, start, end);
|
||||||
|
|
||||||
final long now = System.currentTimeMillis();
|
final long now = System.currentTimeMillis();
|
||||||
final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
|
final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
|
||||||
@@ -910,14 +962,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
* appropriate.
|
* appropriate.
|
||||||
*/
|
*/
|
||||||
private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template,
|
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
|
// We've been using pure XT stats long enough that we no longer need to
|
||||||
// splice DEV and XT together.
|
// splice DEV and XT together.
|
||||||
final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags);
|
final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags);
|
||||||
synchronized (mStatsLock) {
|
synchronized (mStatsLock) {
|
||||||
return mXtStatsCached.getHistory(template, augmentPlan,
|
return mXtStatsCached.getHistory(template, augmentPlan,
|
||||||
UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE,
|
UID_ALL, SET_ALL, TAG_NONE, fields, start, end, accessLevel, callingUid);
|
||||||
accessLevel, callingUid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user