Adding a callback to notify data usage.

Allow holders of android.Manifest.permission#PACKAGE_USAGE_STATS
to be notified when data usage has exceeded a given threshold.
This allows an app to update its data usage metrics without
polling.

Bug: 25812785
Change-Id: I3a4904a97f3c7fbaf8071b460f9ee6ca9c1ba4ed
This commit is contained in:
Antonio Cansado
2015-12-02 08:42:54 -08:00
parent 2bb66f5d48
commit fb502108b4
3 changed files with 223 additions and 0 deletions

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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;
}
}