From fe78ecbb2caa3a647a0bddb4c3bea65d7e2cd736 Mon Sep 17 00:00:00 2001 From: Antonio Cansado Date: Wed, 30 Mar 2016 11:37:18 -0700 Subject: [PATCH] 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 --- core/java/android/app/usage/NetworkStats.java | 14 +- .../app/usage/NetworkStatsManager.java | 225 ++++++++++-------- core/java/android/net/DataUsageRequest.java | 63 +---- .../android/net/INetworkStatsService.aidl | 4 +- .../server/net/NetworkStatsObservers.java | 72 ++---- .../server/net/NetworkStatsService.java | 12 +- 6 files changed, 167 insertions(+), 223 deletions(-) diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index 9963eab9b9..226aa8f270 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -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; } diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 2e3aca46f9..4a2811778a 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -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}. *

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 + *

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); } diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java index 8526584d64..ac9a5a3668 100644 --- a/core/java/android/net/DataUsageRequest.java +++ b/core/java/android/net/DataUsageRequest.java @@ -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. - * - *

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); } } diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 2eea9408f9..e693009c33 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -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); } diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java index 6f781b3ebb..230c2e9510 100644 --- a/services/core/java/com/android/server/net/NetworkStatsObservers.java +++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java @@ -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 { diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 2c2e9b91b5..8610fa1b7b 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -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();