Addressing API council comments on NetworkStatsManager.
Callbacks - DataUsageCallback renamed to UsageCallback - DataUsagePolicy removed; passing in params directly to register method - making it an abstract class - passing in (networkType, subscriberId) that reached its threshold - renaming onLimitReached to onThresholdReached to match existing naming - only monitor single network,subscriberId - no monitoring of specific uids; using device or user wide instead Tags - only owner uid can read its tags - exposing only TAG_NONE to match service side BUG: 27530098 Change-Id: I2b2664da71806868a1e937d2bf4d1f234637509b
This commit is contained in:
@@ -192,15 +192,10 @@ public final class NetworkStats implements AutoCloseable {
|
||||
*/
|
||||
public static final int ROAMING_YES = 0x2;
|
||||
|
||||
/**
|
||||
* Special TAG value matching any tag.
|
||||
*/
|
||||
public static final int TAG_ANY = android.net.NetworkStats.TAG_ALL;
|
||||
|
||||
/**
|
||||
* Special TAG value for total data across all tags
|
||||
*/
|
||||
public static final int TAG_ALL = android.net.NetworkStats.TAG_NONE;
|
||||
public static final int TAG_NONE = android.net.NetworkStats.TAG_NONE;
|
||||
|
||||
private int mUid;
|
||||
private int mTag;
|
||||
@@ -232,8 +227,7 @@ public final class NetworkStats implements AutoCloseable {
|
||||
|
||||
private static int convertTag(int tag) {
|
||||
switch (tag) {
|
||||
case android.net.NetworkStats.TAG_ALL: return TAG_ANY;
|
||||
case android.net.NetworkStats.TAG_NONE: return TAG_ALL;
|
||||
case android.net.NetworkStats.TAG_NONE: return TAG_NONE;
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
@@ -417,9 +411,9 @@ public final class NetworkStats implements AutoCloseable {
|
||||
* Collects summary results and sets summary enumeration mode.
|
||||
* @throws RemoteException
|
||||
*/
|
||||
void startSummaryEnumeration(boolean includeTags) throws RemoteException {
|
||||
void startSummaryEnumeration() throws RemoteException {
|
||||
mSummary = mSession.getSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp,
|
||||
includeTags);
|
||||
false /* includeTags */);
|
||||
mEnumerationIndex = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ public class NetworkStatsManager {
|
||||
* device. Result is a single Bucket aggregated over time, state, uid, tag and roaming. This
|
||||
* means the bucket's start and end timestamp are going to be the same as the 'startTime' and
|
||||
* 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid
|
||||
* {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_ALL}
|
||||
* {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE}
|
||||
* and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
|
||||
*
|
||||
* @param networkType As defined in {@link ConnectivityManager}, e.g.
|
||||
@@ -122,8 +122,11 @@ public class NetworkStatsManager {
|
||||
*/
|
||||
public Bucket querySummaryForDevice(int networkType, String subscriberId,
|
||||
long startTime, long endTime) throws SecurityException, RemoteException {
|
||||
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
||||
if (template == null) {
|
||||
NetworkTemplate template;
|
||||
try {
|
||||
template = createTemplate(networkType, subscriberId);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (DBG) Log.e(TAG, "Cannot create template", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -135,22 +138,11 @@ public class NetworkStatsManager {
|
||||
return bucket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query network usage statistics summaries aggregated across tags.
|
||||
*
|
||||
* #see querySummaryForUser(int, String, long, long, boolean)
|
||||
*/
|
||||
public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
|
||||
long endTime) throws SecurityException, RemoteException {
|
||||
return querySummaryForUser(networkType, subscriberId, startTime, endTime,
|
||||
false /* includeTags */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query network usage statistics summaries. Result is summarised data usage for all uids
|
||||
* belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
|
||||
* This means the bucket's start and end timestamp are going to be the same as the 'startTime'
|
||||
* and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid
|
||||
* and 'endTime' parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid
|
||||
* {@link NetworkStats.Bucket#UID_ALL}.
|
||||
*
|
||||
* @param networkType As defined in {@link ConnectivityManager}, e.g.
|
||||
@@ -161,42 +153,33 @@ public class NetworkStatsManager {
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param endTime End of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param includeTags whether to include network tags. If {@code true}, tags will be returned
|
||||
* and history retention may be shorter.
|
||||
* @return Bucket object or null if permissions are insufficient or error happened during
|
||||
* statistics collection.
|
||||
*/
|
||||
public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
|
||||
long endTime, boolean includeTags) throws SecurityException, RemoteException {
|
||||
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
||||
if (template == null) {
|
||||
long endTime) throws SecurityException, RemoteException {
|
||||
NetworkTemplate template;
|
||||
try {
|
||||
template = createTemplate(networkType, subscriberId);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (DBG) Log.e(TAG, "Cannot create template", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
NetworkStats stats;
|
||||
stats = new NetworkStats(mContext, template, startTime, endTime);
|
||||
stats.startSummaryEnumeration(includeTags);
|
||||
stats.startSummaryEnumeration();
|
||||
|
||||
stats.close();
|
||||
return stats.getSummaryAggregate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query network usage statistics summaries aggregated across tags.
|
||||
*
|
||||
* #see querySummary(int, String, long, long, boolean)
|
||||
*/
|
||||
public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
|
||||
long endTime) throws SecurityException, RemoteException {
|
||||
return querySummary(networkType, subscriberId, startTime, endTime, false /* includeTags */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query network usage statistics summaries. Result filtered to include only uids belonging to
|
||||
* calling user. Result is aggregated over time, hence all buckets will have the same start and
|
||||
* end timestamps. Not aggregated over state or uid or tag. This means buckets' start and end
|
||||
* timestamps are going to be the same as the 'startTime' and 'endTime' parameters. State,
|
||||
* uid and tag are going to vary.
|
||||
* end timestamps. Not aggregated over state or uid. This means buckets' start and end
|
||||
* timestamps are going to be the same as the 'startTime' and 'endTime' parameters.
|
||||
* State and uid are going to vary, and tag is going to be the same.
|
||||
*
|
||||
* @param networkType As defined in {@link ConnectivityManager}, e.g.
|
||||
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
|
||||
@@ -206,21 +189,22 @@ public class NetworkStatsManager {
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param endTime End of period. Defined in terms of "Unix time", see
|
||||
* {@link java.lang.System#currentTimeMillis}.
|
||||
* @param includeTags whether to include network tags. If {@code true}, tags will be returned
|
||||
* and history retention may be shorter.
|
||||
* @return Statistics object or null if permissions are insufficient or error happened during
|
||||
* statistics collection.
|
||||
*/
|
||||
public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
|
||||
long endTime, boolean includeTags) throws SecurityException, RemoteException {
|
||||
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
||||
if (template == null) {
|
||||
long endTime) throws SecurityException, RemoteException {
|
||||
NetworkTemplate template;
|
||||
try {
|
||||
template = createTemplate(networkType, subscriberId);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (DBG) Log.e(TAG, "Cannot create template", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
NetworkStats result;
|
||||
result = new NetworkStats(mContext, template, startTime, endTime);
|
||||
result.startSummaryEnumeration(includeTags);
|
||||
result.startSummaryEnumeration();
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -233,7 +217,7 @@ public class NetworkStatsManager {
|
||||
public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
|
||||
long startTime, long endTime, int uid) throws SecurityException, RemoteException {
|
||||
return queryDetailsForUidTag(networkType, subscriberId, startTime, endTime, uid,
|
||||
NetworkStats.Bucket.TAG_ALL);
|
||||
NetworkStats.Bucket.TAG_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,22 +239,28 @@ 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_ANY} for any tags, use
|
||||
* {@link NetworkStats.Bucket#TAG_ALL} to aggregate over tags.
|
||||
* @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
|
||||
* @return Statistics object or null if permissions are insufficient or error happened during
|
||||
* statistics collection.
|
||||
*/
|
||||
public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
|
||||
long startTime, long endTime, int uid, int tag) throws SecurityException,
|
||||
RemoteException {
|
||||
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
||||
if (template == null) {
|
||||
long startTime, long endTime, int uid, int tag) {
|
||||
NetworkTemplate template;
|
||||
try {
|
||||
template = createTemplate(networkType, subscriberId);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (DBG) Log.e(TAG, "Cannot create template", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
NetworkStats result;
|
||||
result = new NetworkStats(mContext, template, startTime, endTime);
|
||||
result.startHistoryEnumeration(uid, tag);
|
||||
try {
|
||||
result = new NetworkStats(mContext, template, startTime, endTime);
|
||||
result.startHistoryEnumeration(uid, tag);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -280,7 +270,7 @@ public class NetworkStatsManager {
|
||||
* calling user. Result is aggregated over state but not aggregated over time or uid. This means
|
||||
* buckets' start and end timestamps are going to be between 'startTime' and 'endTime'
|
||||
* parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
|
||||
* tag {@link NetworkStats.Bucket#TAG_ALL} and roaming is going to be
|
||||
* tag {@link NetworkStats.Bucket#TAG_NONE} 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
|
||||
@@ -299,44 +289,59 @@ public class NetworkStatsManager {
|
||||
*/
|
||||
public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
|
||||
long endTime) throws SecurityException, RemoteException {
|
||||
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
||||
if (template == null) {
|
||||
NetworkTemplate template;
|
||||
try {
|
||||
template = createTemplate(networkType, subscriberId);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (DBG) Log.e(TAG, "Cannot create template", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
NetworkStats result;
|
||||
result = new NetworkStats(mContext, template, startTime, endTime);
|
||||
result.startUserUidEnumeration();
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @removed */
|
||||
public void registerDataUsageCallback(DataUsagePolicy policy, DataUsageCallback callback,
|
||||
@Nullable Handler handler) {}
|
||||
|
||||
/** @removed */
|
||||
public void registerDataUsageCallback(DataUsagePolicy policy, UsageCallback callback,
|
||||
@Nullable Handler handler) {}
|
||||
|
||||
/** @removed */
|
||||
public void unregisterDataUsageCallback(DataUsageCallback callback) {}
|
||||
|
||||
/**
|
||||
* Registers to receive notifications about data usage on specified networks and uids.
|
||||
* The callbacks will continue to be called as long as the process is live or
|
||||
* {@link #unregisterDataUsageCallback} is called.
|
||||
* Registers to receive notifications about data usage on specified networks.
|
||||
*
|
||||
* @param policy {@link DataUsagePolicy} describing this request.
|
||||
* @param callback The {@link DataUsageCallback} that the system will call when data usage
|
||||
* has exceeded the specified threshold.
|
||||
* #see registerUsageCallback(int, String[], long, UsageCallback, Handler)
|
||||
*/
|
||||
public void registerDataUsageCallback(DataUsagePolicy policy, DataUsageCallback callback) {
|
||||
registerDataUsageCallback(policy, callback, null /* handler */);
|
||||
public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
|
||||
UsageCallback callback) {
|
||||
registerUsageCallback(networkType, subscriberId, thresholdBytes, null /* handler */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers to receive notifications about data usage on specified networks and uids.
|
||||
* The callbacks will continue to be called as long as the process is live or
|
||||
* {@link #unregisterDataUsageCallback} is called.
|
||||
* Registers to receive notifications about data usage on specified networks.
|
||||
*
|
||||
* @param policy {@link DataUsagePolicy} describing this request.
|
||||
* @param callback The {@link DataUsageCallback} that the system will call when data usage
|
||||
* <p>The callbacks will continue to be called as long as the process is live or
|
||||
* {@link #unregisterUsageCallback} is called.
|
||||
*
|
||||
* @param networkType Type of network to monitor. Either
|
||||
{@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
|
||||
* @param subscriberId If applicable, the subscriber id of the network interface.
|
||||
* @param thresholdBytes Threshold in bytes to be notified on.
|
||||
* @param callback The {@link UsageCallback} that the system will call when data usage
|
||||
* has exceeded the specified threshold.
|
||||
* @param handler to dispatch callback events through, otherwise if {@code null} it uses
|
||||
* the calling thread.
|
||||
*/
|
||||
public void registerDataUsageCallback(DataUsagePolicy policy, DataUsageCallback callback,
|
||||
@Nullable Handler handler) {
|
||||
checkNotNull(policy, "DataUsagePolicy cannot be null");
|
||||
checkNotNull(callback, "DataUsageCallback cannot be null");
|
||||
public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
|
||||
UsageCallback callback, @Nullable Handler handler) {
|
||||
checkNotNull(callback, "UsageCallback cannot be null");
|
||||
|
||||
final Looper looper;
|
||||
if (handler == null) {
|
||||
@@ -345,62 +350,72 @@ public class NetworkStatsManager {
|
||||
looper = handler.getLooper();
|
||||
}
|
||||
|
||||
if (DBG) Log.d(TAG, "registerDataUsageCallback called with " + policy);
|
||||
|
||||
NetworkTemplate[] templates;
|
||||
if (policy.subscriberIds == null || policy.subscriberIds.length == 0) {
|
||||
templates = new NetworkTemplate[1];
|
||||
templates[0] = createTemplate(policy.networkType, null /* subscriberId */);
|
||||
} else {
|
||||
templates = new NetworkTemplate[policy.subscriberIds.length];
|
||||
for (int i = 0; i < policy.subscriberIds.length; i++) {
|
||||
templates[i] = createTemplate(policy.networkType, policy.subscriberIds[i]);
|
||||
}
|
||||
if (DBG) {
|
||||
Log.d(TAG, "registerUsageCallback called with: {"
|
||||
+ " networkType=" + networkType
|
||||
+ " subscriberId=" + subscriberId
|
||||
+ " thresholdBytes=" + thresholdBytes
|
||||
+ " }");
|
||||
}
|
||||
|
||||
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
||||
DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
|
||||
templates, policy.uids, policy.thresholdInBytes);
|
||||
template, thresholdBytes);
|
||||
try {
|
||||
CallbackHandler callbackHandler = new CallbackHandler(looper, callback);
|
||||
callback.request = mService.registerDataUsageCallback(
|
||||
CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
|
||||
subscriberId, callback);
|
||||
callback.request = mService.registerUsageCallback(
|
||||
mContext.getOpPackageName(), request, new Messenger(callbackHandler),
|
||||
new Binder());
|
||||
if (DBG) Log.d(TAG, "registerDataUsageCallback returned " + callback.request);
|
||||
if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
|
||||
|
||||
if (callback.request == null) {
|
||||
Log.e(TAG, "Request from callback is null; should not happen");
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
if (DBG) Log.d(TAG, "Remote exception when registering callback");
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters callbacks on data usage.
|
||||
*
|
||||
* @param callback The {@link DataUsageCallback} used when registering.
|
||||
* @param callback The {@link UsageCallback} used when registering.
|
||||
*/
|
||||
public void unregisterDataUsageCallback(DataUsageCallback callback) {
|
||||
public void unregisterUsageCallback(UsageCallback callback) {
|
||||
if (callback == null || callback.request == null
|
||||
|| callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
|
||||
throw new IllegalArgumentException("Invalid DataUsageCallback");
|
||||
throw new IllegalArgumentException("Invalid UsageCallback");
|
||||
}
|
||||
try {
|
||||
mService.unregisterDataUsageRequest(callback.request);
|
||||
mService.unregisterUsageRequest(callback.request);
|
||||
} catch (RemoteException e) {
|
||||
if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for data usage callbacks. Should be extended by applications wanting
|
||||
* notifications.
|
||||
*/
|
||||
public static class DataUsageCallback {
|
||||
/**
|
||||
* Called when data usage has reached the given policy threshold.
|
||||
*/
|
||||
/** @removed */
|
||||
public static abstract class DataUsageCallback {
|
||||
/** @removed */
|
||||
@Deprecated
|
||||
public void onLimitReached() {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for usage callbacks. Should be extended by applications wanting notifications.
|
||||
*/
|
||||
public static abstract class UsageCallback {
|
||||
|
||||
/**
|
||||
* Called when data usage has reached the given threshold.
|
||||
*/
|
||||
public abstract void onThresholdReached(int networkType, String subscriberId);
|
||||
|
||||
/**
|
||||
* @hide used for internal bookkeeping
|
||||
*/
|
||||
private DataUsageRequest request;
|
||||
}
|
||||
|
||||
@@ -414,18 +429,24 @@ public class NetworkStatsManager {
|
||||
template = NetworkTemplate.buildTemplateWifiWildcard();
|
||||
} break;
|
||||
default: {
|
||||
Log.w(TAG, "Cannot create template for network type " + networkType
|
||||
+ ", subscriberId '" + NetworkIdentity.scrubSubscriberId(subscriberId) +
|
||||
"'.");
|
||||
throw new IllegalArgumentException("Cannot create template for network type "
|
||||
+ networkType + ", subscriberId '"
|
||||
+ NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
|
||||
}
|
||||
}
|
||||
return template;
|
||||
}
|
||||
|
||||
private static class CallbackHandler extends Handler {
|
||||
private DataUsageCallback mCallback;
|
||||
CallbackHandler(Looper looper, DataUsageCallback callback) {
|
||||
private final int mNetworkType;
|
||||
private final String mSubscriberId;
|
||||
private UsageCallback mCallback;
|
||||
|
||||
CallbackHandler(Looper looper, int networkType, String subscriberId,
|
||||
UsageCallback callback) {
|
||||
super(looper);
|
||||
mNetworkType = networkType;
|
||||
mSubscriberId = subscriberId;
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@@ -437,7 +458,7 @@ public class NetworkStatsManager {
|
||||
switch (message.what) {
|
||||
case CALLBACK_LIMIT_REACHED: {
|
||||
if (mCallback != null) {
|
||||
mCallback.onLimitReached();
|
||||
mCallback.onThresholdReached(mNetworkType, mSubscriberId);
|
||||
} else {
|
||||
Log.e(TAG, "limit reached with released callback for " + request);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.net.NetworkTemplate;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -28,56 +27,33 @@ import java.util.Objects;
|
||||
* {@link android.app.usage.NetworkStatsManager#registerDataUsageCallback}.
|
||||
* If no {@code uid}s are set, callbacks are restricted to device-owners,
|
||||
* carrier-privileged apps, or system apps.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class DataUsageRequest implements Parcelable {
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final String PARCELABLE_KEY = "DataUsageRequest";
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final int REQUEST_ID_UNSET = 0;
|
||||
|
||||
/**
|
||||
* Identifies the request. {@link DataUsageRequest}s should only be constructed by
|
||||
* the Framework and it is used internally to identify the request.
|
||||
* @hide
|
||||
*/
|
||||
public final int requestId;
|
||||
|
||||
/**
|
||||
* Set of {@link NetworkTemplate}s describing the networks to monitor.
|
||||
* @hide
|
||||
* {@link NetworkTemplate} describing the network to monitor.
|
||||
*/
|
||||
public final NetworkTemplate[] templates;
|
||||
|
||||
/**
|
||||
* Set of UIDs of which to monitor data usage.
|
||||
*
|
||||
* <p>If not {@code null}, the caller will be notified when any of the uids exceed
|
||||
* the given threshold. If {@code null} all uids for which the calling process has access
|
||||
* to stats will be monitored.
|
||||
* @hide
|
||||
*/
|
||||
public final int[] uids;
|
||||
public final NetworkTemplate template;
|
||||
|
||||
/**
|
||||
* Threshold in bytes to be notified on.
|
||||
* @hide
|
||||
*/
|
||||
public final long thresholdInBytes;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public DataUsageRequest(int requestId, NetworkTemplate[] templates, int[] uids,
|
||||
long thresholdInBytes) {
|
||||
public DataUsageRequest(int requestId, NetworkTemplate template, long thresholdInBytes) {
|
||||
this.requestId = requestId;
|
||||
this.templates = templates;
|
||||
this.uids = uids;
|
||||
this.template = template;
|
||||
this.thresholdInBytes = thresholdInBytes;
|
||||
}
|
||||
|
||||
@@ -89,8 +65,7 @@ public final class DataUsageRequest implements Parcelable {
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(requestId);
|
||||
dest.writeTypedArray(templates, flags);
|
||||
dest.writeIntArray(uids);
|
||||
dest.writeParcelable(template, flags);
|
||||
dest.writeLong(thresholdInBytes);
|
||||
}
|
||||
|
||||
@@ -99,11 +74,10 @@ public final class DataUsageRequest implements Parcelable {
|
||||
@Override
|
||||
public DataUsageRequest createFromParcel(Parcel in) {
|
||||
int requestId = in.readInt();
|
||||
NetworkTemplate[] templates = in.createTypedArray(NetworkTemplate.CREATOR);
|
||||
int[] uids = in.createIntArray();
|
||||
NetworkTemplate template = in.readParcelable(null);
|
||||
long thresholdInBytes = in.readLong();
|
||||
DataUsageRequest result = new DataUsageRequest(requestId,
|
||||
templates, uids, thresholdInBytes);
|
||||
DataUsageRequest result = new DataUsageRequest(requestId, template,
|
||||
thresholdInBytes);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -116,8 +90,7 @@ public final class DataUsageRequest implements Parcelable {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DataUsageRequest [ requestId=" + requestId
|
||||
+ ", networkTemplates=" + Arrays.toString(templates)
|
||||
+ ", uids=" + Arrays.toString(uids)
|
||||
+ ", networkTemplate=" + template
|
||||
+ ", thresholdInBytes=" + thresholdInBytes + " ]";
|
||||
}
|
||||
|
||||
@@ -126,23 +99,13 @@ public final class DataUsageRequest implements Parcelable {
|
||||
if (obj instanceof DataUsageRequest == false) return false;
|
||||
DataUsageRequest that = (DataUsageRequest) obj;
|
||||
return that.requestId == this.requestId
|
||||
&& Arrays.deepEquals(that.templates, this.templates)
|
||||
&& Arrays.equals(that.uids, this.uids)
|
||||
&& Objects.equals(that.template, this.template)
|
||||
&& that.thresholdInBytes == this.thresholdInBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// Start with a non-zero constant.
|
||||
int result = 17;
|
||||
|
||||
// Include a hash for each field.
|
||||
result = 31 * result + requestId;
|
||||
result = 31 * result + Arrays.deepHashCode(templates);
|
||||
result = 31 * result + Arrays.hashCode(uids);
|
||||
result = 31 * result + (int) (thresholdInBytes ^ (thresholdInBytes >>> 32));
|
||||
|
||||
return result;
|
||||
return Objects.hash(requestId, template, thresholdInBytes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -61,10 +61,10 @@ interface INetworkStatsService {
|
||||
void advisePersistThreshold(long thresholdBytes);
|
||||
|
||||
/** Registers a callback on data usage. */
|
||||
DataUsageRequest registerDataUsageCallback(String callingPackage,
|
||||
DataUsageRequest registerUsageCallback(String callingPackage,
|
||||
in DataUsageRequest request, in Messenger messenger, in IBinder binder);
|
||||
|
||||
/** Unregisters a callback on data usage. */
|
||||
void unregisterDataUsageRequest(in DataUsageRequest request);
|
||||
void unregisterUsageRequest(in DataUsageRequest request);
|
||||
|
||||
}
|
||||
|
||||
@@ -81,8 +81,6 @@ class NetworkStatsObservers {
|
||||
*/
|
||||
public DataUsageRequest register(DataUsageRequest inputRequest, Messenger messenger,
|
||||
IBinder binder, int callingUid, @NetworkStatsAccess.Level int accessLevel) {
|
||||
checkVisibilityUids(callingUid, accessLevel, inputRequest.uids);
|
||||
|
||||
DataUsageRequest request = buildRequest(inputRequest);
|
||||
RequestInfo requestInfo = buildRequestInfo(request, messenger, binder, callingUid,
|
||||
accessLevel);
|
||||
@@ -211,14 +209,13 @@ class NetworkStatsObservers {
|
||||
+ ". Overriding to a safer default of " + thresholdInBytes + " bytes");
|
||||
}
|
||||
return new DataUsageRequest(mNextDataUsageRequestId.incrementAndGet(),
|
||||
request.templates, request.uids, thresholdInBytes);
|
||||
request.template, thresholdInBytes);
|
||||
}
|
||||
|
||||
private RequestInfo buildRequestInfo(DataUsageRequest request,
|
||||
Messenger messenger, IBinder binder, int callingUid,
|
||||
@NetworkStatsAccess.Level int accessLevel) {
|
||||
if (accessLevel <= NetworkStatsAccess.Level.USER
|
||||
|| request.uids != null && request.uids.length > 0) {
|
||||
if (accessLevel <= NetworkStatsAccess.Level.USER) {
|
||||
return new UserUsageRequestInfo(this, request, messenger, binder, callingUid,
|
||||
accessLevel);
|
||||
} else {
|
||||
@@ -229,19 +226,6 @@ class NetworkStatsObservers {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkVisibilityUids(int callingUid, @NetworkStatsAccess.Level int accessLevel,
|
||||
int[] uids) {
|
||||
if (uids == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < uids.length; i++) {
|
||||
if (!NetworkStatsAccess.isAccessibleToUser(uids[i], callingUid, accessLevel)) {
|
||||
throw new SecurityException("Caller " + callingUid + " cannot monitor network stats"
|
||||
+ " for uid " + uids[i] + " with accessLevel " + accessLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks information relevant to a data usage observer.
|
||||
* It will notice when the calling process dies so we can self-expire.
|
||||
@@ -359,15 +343,13 @@ class NetworkStatsObservers {
|
||||
|
||||
@Override
|
||||
protected boolean checkStats() {
|
||||
for (int i = 0; i < mRequest.templates.length; i++) {
|
||||
long bytesSoFar = getTotalBytesForNetwork(mRequest.templates[i]);
|
||||
if (LOGV) {
|
||||
Slog.v(TAG, bytesSoFar + " bytes so far since notification for "
|
||||
+ mRequest.templates[i]);
|
||||
}
|
||||
if (bytesSoFar > mRequest.thresholdInBytes) {
|
||||
return true;
|
||||
}
|
||||
long bytesSoFar = getTotalBytesForNetwork(mRequest.template);
|
||||
if (LOGV) {
|
||||
Slog.v(TAG, bytesSoFar + " bytes so far since notification for "
|
||||
+ mRequest.template);
|
||||
}
|
||||
if (bytesSoFar > mRequest.thresholdInBytes) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -405,20 +387,17 @@ class NetworkStatsObservers {
|
||||
|
||||
@Override
|
||||
protected boolean checkStats() {
|
||||
int[] uidsToMonitor = getUidsToMonitor();
|
||||
int[] uidsToMonitor = mCollection.getRelevantUids(mAccessLevel, mCallingUid);
|
||||
|
||||
for (int i = 0; i < mRequest.templates.length; i++) {
|
||||
for (int j = 0; j < uidsToMonitor.length; j++) {
|
||||
long bytesSoFar = getTotalBytesForNetworkUid(mRequest.templates[i],
|
||||
uidsToMonitor[j]);
|
||||
for (int i = 0; i < uidsToMonitor.length; i++) {
|
||||
long bytesSoFar = getTotalBytesForNetworkUid(mRequest.template, uidsToMonitor[i]);
|
||||
|
||||
if (LOGV) {
|
||||
Slog.v(TAG, bytesSoFar + " bytes so far since notification for "
|
||||
+ mRequest.templates[i] + " for uid=" + uidsToMonitor[j]);
|
||||
}
|
||||
if (bytesSoFar > mRequest.thresholdInBytes) {
|
||||
return true;
|
||||
}
|
||||
if (LOGV) {
|
||||
Slog.v(TAG, bytesSoFar + " bytes so far since notification for "
|
||||
+ mRequest.template + " for uid=" + uidsToMonitor[i]);
|
||||
}
|
||||
if (bytesSoFar > mRequest.thresholdInBytes) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -453,21 +432,6 @@ class NetworkStatsObservers {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private int[] getUidsToMonitor() {
|
||||
if (mRequest.uids == null || mRequest.uids.length == 0) {
|
||||
return mCollection.getRelevantUids(mAccessLevel, mCallingUid);
|
||||
}
|
||||
// Pick only uids from the request that are currently accessible to the user
|
||||
IntArray accessibleUids = new IntArray(mRequest.uids.length);
|
||||
for (int i = 0; i < mRequest.uids.length; i++) {
|
||||
int uid = mRequest.uids[i];
|
||||
if (NetworkStatsAccess.isAccessibleToUser(uid, mCallingUid, mAccessLevel)) {
|
||||
accessibleUids.add(uid);
|
||||
}
|
||||
}
|
||||
return accessibleUids.toArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static class StatsContext {
|
||||
|
||||
@@ -578,9 +578,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
if (tag == TAG_NONE) {
|
||||
return getUidComplete().getHistory(template, uid, set, tag, fields, start, end,
|
||||
accessLevel);
|
||||
} else {
|
||||
} else if (uid == Binder.getCallingUid()) {
|
||||
return getUidTagComplete().getHistory(template, uid, set, tag, fields,
|
||||
start, end, accessLevel);
|
||||
} else {
|
||||
throw new SecurityException("Calling package " + mCallingPackage
|
||||
+ " cannot access tag information from a different uid");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -761,12 +764,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataUsageRequest registerDataUsageCallback(String callingPackage,
|
||||
public DataUsageRequest registerUsageCallback(String callingPackage,
|
||||
DataUsageRequest request, Messenger messenger, IBinder binder) {
|
||||
checkNotNull(callingPackage, "calling package is null");
|
||||
checkNotNull(request, "DataUsageRequest is null");
|
||||
checkNotNull(request.templates, "NetworkTemplate is null");
|
||||
checkArgument(request.templates.length > 0);
|
||||
checkNotNull(request.template, "NetworkTemplate is null");
|
||||
checkNotNull(messenger, "messenger is null");
|
||||
checkNotNull(binder, "binder is null");
|
||||
|
||||
@@ -788,7 +790,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterDataUsageRequest(DataUsageRequest request) {
|
||||
public void unregisterUsageRequest(DataUsageRequest request) {
|
||||
checkNotNull(request, "DataUsageRequest is null");
|
||||
|
||||
int callingUid = Binder.getCallingUid();
|
||||
|
||||
Reference in New Issue
Block a user