diff options
| -rw-r--r-- | api/current.txt | 30 | ||||
| -rw-r--r-- | api/system-current.txt | 30 | ||||
| -rw-r--r-- | api/test-current.txt | 30 | ||||
| -rw-r--r-- | core/java/android/app/usage/DataUsagePolicy.java | 174 | ||||
| -rw-r--r-- | core/java/android/app/usage/NetworkStatsManager.java | 61 | ||||
| -rw-r--r-- | core/java/android/net/DataUsageRequest.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/net/DataUsageRequest.java | 143 |
7 files changed, 487 insertions, 0 deletions
diff --git a/api/current.txt b/api/current.txt index ba73ca2e8647..f9d0740c4e69 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6320,6 +6320,22 @@ package android.app.usage { field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR; } + public class DataUsagePolicy { + field public final int networkType; + field public final java.lang.String[] subscriberIds; + field public final long thresholdInBytes; + field public final int[] uids; + } + + public static class DataUsagePolicy.Builder { + ctor public DataUsagePolicy.Builder(); + method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String); + method public android.app.usage.DataUsagePolicy.Builder addUid(int); + method public android.app.usage.DataUsagePolicy build(); + method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int); + method public android.app.usage.DataUsagePolicy.Builder setThreshold(long); + } + public final class NetworkStats implements java.lang.AutoCloseable { method public void close(); method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket); @@ -6360,6 +6376,14 @@ package android.app.usage { method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException; method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException; method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException; + method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback); + method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler); + method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback); + } + + public static class NetworkStatsManager.DataUsageCallback { + ctor public NetworkStatsManager.DataUsageCallback(); + method public void onLimitReached(); } public final class UsageEvents implements android.os.Parcelable { @@ -23445,6 +23469,12 @@ package android.net { method public int getUid(); } + public class DataUsageRequest implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.net.DataUsageRequest> CREATOR; + } + public class DhcpInfo implements android.os.Parcelable { ctor public DhcpInfo(); method public int describeContents(); diff --git a/api/system-current.txt b/api/system-current.txt index 10d1b04c4fde..e4c9fc8866c2 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6577,6 +6577,22 @@ package android.app.usage { field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR; } + public class DataUsagePolicy { + field public final int networkType; + field public final java.lang.String[] subscriberIds; + field public final long thresholdInBytes; + field public final int[] uids; + } + + public static class DataUsagePolicy.Builder { + ctor public DataUsagePolicy.Builder(); + method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String); + method public android.app.usage.DataUsagePolicy.Builder addUid(int); + method public android.app.usage.DataUsagePolicy build(); + method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int); + method public android.app.usage.DataUsagePolicy.Builder setThreshold(long); + } + public final class NetworkStats implements java.lang.AutoCloseable { method public void close(); method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket); @@ -6617,6 +6633,14 @@ package android.app.usage { method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException; method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException; method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException; + method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback); + method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler); + method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback); + } + + public static class NetworkStatsManager.DataUsageCallback { + ctor public NetworkStatsManager.DataUsageCallback(); + method public void onLimitReached(); } public final class UsageEvents implements android.os.Parcelable { @@ -25250,6 +25274,12 @@ package android.net { method public int getUid(); } + public class DataUsageRequest implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.net.DataUsageRequest> CREATOR; + } + public class DhcpInfo implements android.os.Parcelable { ctor public DhcpInfo(); method public int describeContents(); diff --git a/api/test-current.txt b/api/test-current.txt index a667a5047559..6d5dd34570a7 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -6322,6 +6322,22 @@ package android.app.usage { field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR; } + public class DataUsagePolicy { + field public final int networkType; + field public final java.lang.String[] subscriberIds; + field public final long thresholdInBytes; + field public final int[] uids; + } + + public static class DataUsagePolicy.Builder { + ctor public DataUsagePolicy.Builder(); + method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String); + method public android.app.usage.DataUsagePolicy.Builder addUid(int); + method public android.app.usage.DataUsagePolicy build(); + method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int); + method public android.app.usage.DataUsagePolicy.Builder setThreshold(long); + } + public final class NetworkStats implements java.lang.AutoCloseable { method public void close(); method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket); @@ -6362,6 +6378,14 @@ package android.app.usage { method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException; method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException; method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException; + method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback); + method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler); + method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback); + } + + public static class NetworkStatsManager.DataUsageCallback { + ctor public NetworkStatsManager.DataUsageCallback(); + method public void onLimitReached(); } public final class UsageEvents implements android.os.Parcelable { @@ -23454,6 +23478,12 @@ package android.net { method public int getUid(); } + public class DataUsageRequest implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.net.DataUsageRequest> CREATOR; + } + public class DhcpInfo implements android.os.Parcelable { ctor public DhcpInfo(); method public int describeContents(); diff --git a/core/java/android/app/usage/DataUsagePolicy.java b/core/java/android/app/usage/DataUsagePolicy.java new file mode 100644 index 000000000000..5a5dcbc0ba2c --- /dev/null +++ b/core/java/android/app/usage/DataUsagePolicy.java @@ -0,0 +1,174 @@ +/** + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package android.app.usage; + +import android.net.ConnectivityManager; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.IntArray; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +/** + * Defines a policy for data usage callbacks, made through {@link DataUsagePolicy.Builder} and used + * to be notified on data usage via {@link NetworkStatsManager#registerDataUsageCallback}. + */ +public class DataUsagePolicy { + + /** + * Network type to be monitored, as defined in {@link ConnectivityManager}, e.g. + * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} etc. + */ + public final int networkType; + + /** + * Set of subscriber ids to be monitored for the given network type. May be empty if not + * applicable. + * <p>Should not be modified once created. + */ + public final String[] subscriberIds; + + /** + * 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 empty all uids for which the calling process has access + * to stats will be monitored. + * <p>Should not be modified once created. + */ + public final int[] uids; + + /** + * Threshold in bytes to be notified on. + */ + public final long thresholdInBytes; + + /** + * @hide + */ + DataUsagePolicy(int networkType, String[] subscriberIds, int[] uids, + long thresholdInBytes) { + this.networkType = networkType; + this.subscriberIds = subscriberIds; + this.uids = uids; + this.thresholdInBytes = thresholdInBytes; + } + + /** + * Builder used to create {@link DataUsagePolicy} objects. + */ + public static class Builder { + private static final int INVALID_NETWORK_TYPE = -1; + private int mNetworkType = INVALID_NETWORK_TYPE; + private List<String> mSubscriberList = new ArrayList<>(); + private IntArray mUids = new IntArray(); + private long mThresholdInBytes; + + /** + * Default constructor for Builder. + */ + public Builder() {} + + /** + * Build {@link DataUsagePolicy} given the current policies. + */ + public DataUsagePolicy build() { + if (mNetworkType == INVALID_NETWORK_TYPE) { + throw new IllegalArgumentException( + "DataUsagePolicy requires a valid network type to be set"); + } + return new DataUsagePolicy(mNetworkType, + mSubscriberList.toArray(new String[mSubscriberList.size()]), + mUids.toArray(), mThresholdInBytes); + } + + /** + * Specifies that the given {@code subscriberId} should be monitored. + * + * @param subscriberId the subscriber id of the network interface. + */ + public Builder addSubscriberId(String subscriberId) { + mSubscriberList.add(subscriberId); + return this; + } + + /** + * Specifies that the given {@code uid} should be monitored. + */ + public Builder addUid(int uid) { + mUids.add(uid); + return this; + } + + /** + * Specifies that the callback should monitor the given network. It is mandatory + * to set one. + * + * @param networkType As defined in {@link ConnectivityManager}, e.g. + * {@link ConnectivityManager#TYPE_MOBILE}, + * {@link ConnectivityManager#TYPE_WIFI}, etc. + */ + public Builder setNetworkType(int networkType) { + mNetworkType = networkType; + return this; + } + + /** + * Sets the threshold in bytes on which the listener should be called. The framework may + * impose a minimum threshold to avoid too many notifications to be triggered. + */ + public Builder setThreshold(long thresholdInBytes) { + mThresholdInBytes = thresholdInBytes; + return this; + } + } + + @Override + public String toString() { + return "DataUsagePolicy [ networkType=" + networkType + + ", subscriberIds=" + Arrays.toString(subscriberIds) + + ", uids=" + Arrays.toString(uids) + + ", thresholdInBytes=" + thresholdInBytes + " ]"; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof DataUsagePolicy == false) return false; + DataUsagePolicy that = (DataUsagePolicy) obj; + return that.networkType == this.networkType + && Arrays.deepEquals(that.subscriberIds, this.subscriberIds) + && Arrays.equals(that.uids, this.uids) + && 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 + networkType; + result = 31 * result + Arrays.deepHashCode(subscriberIds); + result = 31 * result + Arrays.hashCode(uids); + result = 31 * result + (int) (thresholdInBytes ^ (thresholdInBytes >>> 32)); + + return result; + } +} diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 4dc636b078b7..13aeef0058bb 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -16,12 +16,17 @@ package android.app.usage; +import static com.android.internal.util.Preconditions.checkNotNull; + +import android.annotation.Nullable; import android.app.usage.NetworkStats.Bucket; import android.content.Context; import android.net.ConnectivityManager; +import android.net.DataUsageRequest; import android.net.NetworkIdentity; import android.net.NetworkTemplate; import android.os.Build; +import android.os.Handler; import android.os.RemoteException; import android.util.Log; @@ -288,6 +293,62 @@ public class NetworkStatsManager { return result; } + /** + * 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. + * + * @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. + */ + public void registerDataUsageCallback(DataUsagePolicy policy, DataUsageCallback callback) { + registerDataUsageCallback(policy, callback, 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. + * + * @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. + * @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"); + + // TODO: Implement stub. + } + + /** + * Unregisters callbacks on data usage. + * + * @param callback The {@link DataUsageCallback} used when registering. + */ + public void unregisterDataUsageCallback(DataUsageCallback callback) { + checkNotNull(callback, "DataUsageCallback cannot be null"); + + // TODO: Implement stub. + } + + /** + * 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. + */ + public void onLimitReached() {} + + private DataUsageRequest request; + } + private static NetworkTemplate createTemplate(int networkType, String subscriberId) { NetworkTemplate template = null; switch (networkType) { diff --git a/core/java/android/net/DataUsageRequest.aidl b/core/java/android/net/DataUsageRequest.aidl new file mode 100644 index 000000000000..d1937c7b8c62 --- /dev/null +++ b/core/java/android/net/DataUsageRequest.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +parcelable DataUsageRequest; diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java new file mode 100644 index 000000000000..0e46f4c0cbdf --- /dev/null +++ b/core/java/android/net/DataUsageRequest.java @@ -0,0 +1,143 @@ +/** + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package android.net; + +import android.net.NetworkTemplate; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Arrays; +import java.util.Objects; + +/** + * Defines a request to register a callbacks. Used to be notified on data usage via + * {@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. + */ +public class DataUsageRequest implements Parcelable { + + /** + * @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 + */ + 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; + + /** + * Threshold in bytes to be notified on. + * @hide + */ + public final long thresholdInBytes; + + /** + * @hide + */ + public DataUsageRequest(int requestId, NetworkTemplate[] templates, int[] uids, + long thresholdInBytes) { + this.requestId = requestId; + this.templates = templates; + this.uids = uids; + this.thresholdInBytes = thresholdInBytes; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(requestId); + dest.writeTypedArray(templates, flags); + dest.writeIntArray(uids); + dest.writeLong(thresholdInBytes); + } + + public static final Creator<DataUsageRequest> CREATOR = + new Creator<DataUsageRequest>() { + @Override + public DataUsageRequest createFromParcel(Parcel in) { + int requestId = in.readInt(); + NetworkTemplate[] templates = in.createTypedArray(NetworkTemplate.CREATOR); + int[] uids = in.createIntArray(); + long thresholdInBytes = in.readLong(); + DataUsageRequest result = new DataUsageRequest(requestId, + templates, uids, thresholdInBytes); + return result; + } + + @Override + public DataUsageRequest[] newArray(int size) { + return new DataUsageRequest[size]; + } + }; + + @Override + public String toString() { + return "DataUsageRequest [ requestId=" + requestId + + ", networkTemplates=" + Arrays.toString(templates) + + ", uids=" + Arrays.toString(uids) + + ", thresholdInBytes=" + thresholdInBytes + " ]"; + } + + @Override + public boolean equals(Object obj) { + 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) + && 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; + } + +} |