Snap for 6306509 from b1f2e3d0211be00397dcacc36296bf71800d3bbd to mainline-release
Change-Id: I4901b261694118fa1e9e82f927236842c4600e0b
This commit is contained in:
@@ -29,10 +29,10 @@ import android.net.ConnectivityManager;
|
|||||||
import android.net.DataUsageRequest;
|
import android.net.DataUsageRequest;
|
||||||
import android.net.INetworkStatsService;
|
import android.net.INetworkStatsService;
|
||||||
import android.net.NetworkIdentity;
|
import android.net.NetworkIdentity;
|
||||||
|
import android.net.NetworkStack;
|
||||||
import android.net.NetworkTemplate;
|
import android.net.NetworkTemplate;
|
||||||
import android.net.netstats.provider.AbstractNetworkStatsProvider;
|
import android.net.netstats.provider.INetworkStatsProviderCallback;
|
||||||
import android.net.netstats.provider.NetworkStatsProviderCallback;
|
import android.net.netstats.provider.NetworkStatsProvider;
|
||||||
import android.net.netstats.provider.NetworkStatsProviderWrapper;
|
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -527,32 +527,53 @@ public class NetworkStatsManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a custom provider of {@link android.net.NetworkStats} to provide network statistics
|
* Registers a custom provider of {@link android.net.NetworkStats} to provide network statistics
|
||||||
* to the system. To unregister, invoke {@link NetworkStatsProviderCallback#unregister()}.
|
* to the system. To unregister, invoke {@link #unregisterNetworkStatsProvider}.
|
||||||
* Note that no de-duplication of statistics between providers is performed, so each provider
|
* Note that no de-duplication of statistics between providers is performed, so each provider
|
||||||
* must only report network traffic that is not being reported by any other provider.
|
* must only report network traffic that is not being reported by any other provider. Also note
|
||||||
|
* that the provider cannot be re-registered after unregistering.
|
||||||
*
|
*
|
||||||
* @param tag a human readable identifier of the custom network stats provider. This is only
|
* @param tag a human readable identifier of the custom network stats provider. This is only
|
||||||
* used for debugging.
|
* used for debugging.
|
||||||
* @param provider the subclass of {@link AbstractNetworkStatsProvider} that needs to be
|
* @param provider the subclass of {@link NetworkStatsProvider} that needs to be
|
||||||
* registered to the system.
|
* registered to the system.
|
||||||
* @return a {@link NetworkStatsProviderCallback}, which can be used to report events to the
|
|
||||||
* system or unregister the provider.
|
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
@RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
|
@RequiresPermission(anyOf = {
|
||||||
@NonNull public NetworkStatsProviderCallback registerNetworkStatsProvider(
|
android.Manifest.permission.NETWORK_STATS_PROVIDER,
|
||||||
|
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
|
||||||
|
@NonNull public void registerNetworkStatsProvider(
|
||||||
@NonNull String tag,
|
@NonNull String tag,
|
||||||
@NonNull AbstractNetworkStatsProvider provider) {
|
@NonNull NetworkStatsProvider provider) {
|
||||||
try {
|
try {
|
||||||
final NetworkStatsProviderWrapper wrapper = new NetworkStatsProviderWrapper(provider);
|
if (provider.getProviderCallbackBinder() != null) {
|
||||||
return new NetworkStatsProviderCallback(
|
throw new IllegalArgumentException("provider is already registered");
|
||||||
mService.registerNetworkStatsProvider(tag, wrapper));
|
}
|
||||||
|
final INetworkStatsProviderCallback cbBinder =
|
||||||
|
mService.registerNetworkStatsProvider(tag, provider.getProviderBinder());
|
||||||
|
provider.setProviderCallbackBinder(cbBinder);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowAsRuntimeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters an instance of {@link NetworkStatsProvider}.
|
||||||
|
*
|
||||||
|
* @param provider the subclass of {@link NetworkStatsProvider} that needs to be
|
||||||
|
* unregistered to the system.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
@RequiresPermission(anyOf = {
|
||||||
|
android.Manifest.permission.NETWORK_STATS_PROVIDER,
|
||||||
|
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
|
||||||
|
@NonNull public void unregisterNetworkStatsProvider(@NonNull NetworkStatsProvider provider) {
|
||||||
|
try {
|
||||||
|
provider.getProviderCallbackBinderOrThrow().unregister();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
e.rethrowAsRuntimeException();
|
e.rethrowAsRuntimeException();
|
||||||
}
|
}
|
||||||
// Unreachable code, but compiler doesn't know about it.
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
|
private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import static android.os.Process.CLAT_UID;
|
|||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
@@ -58,9 +57,12 @@ import java.util.function.Predicate;
|
|||||||
public final class NetworkStats implements Parcelable {
|
public final class NetworkStats implements Parcelable {
|
||||||
private static final String TAG = "NetworkStats";
|
private static final String TAG = "NetworkStats";
|
||||||
|
|
||||||
/** {@link #iface} value when interface details unavailable. */
|
/**
|
||||||
@SuppressLint("CompileTimeConstant")
|
* {@link #iface} value when interface details unavailable.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
@Nullable public static final String IFACE_ALL = null;
|
@Nullable public static final String IFACE_ALL = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Virtual network interface for video telephony. This is for VT data usage counting
|
* Virtual network interface for video telephony. This is for VT data usage counting
|
||||||
* purpose.
|
* purpose.
|
||||||
@@ -248,7 +250,13 @@ public final class NetworkStats implements Parcelable {
|
|||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
private long[] operations;
|
private long[] operations;
|
||||||
|
|
||||||
/** @hide */
|
/**
|
||||||
|
* Basic element of network statistics. Contains the number of packets and number of bytes
|
||||||
|
* transferred on both directions in a given set of conditions. See
|
||||||
|
* {@link Entry#Entry(String, int, int, int, int, int, int, long, long, long, long, long)}.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
public static class Entry {
|
public static class Entry {
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -319,6 +327,35 @@ public final class NetworkStats implements Parcelable {
|
|||||||
rxBytes, rxPackets, txBytes, txPackets, operations);
|
rxBytes, rxPackets, txBytes, txPackets, operations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a {@link Entry} object by giving statistics of packet and byte transferred on
|
||||||
|
* both direction, and associated with a set of given conditions.
|
||||||
|
*
|
||||||
|
* @param iface interface name of this {@link Entry}. Or null if not specified.
|
||||||
|
* @param uid uid of this {@link Entry}. {@link #UID_TETHERING} if this {@link Entry} is
|
||||||
|
* for tethering. Or {@link #UID_ALL} if this {@link NetworkStats} is only
|
||||||
|
* counting iface stats.
|
||||||
|
* @param set usage state of this {@link Entry}. Should be one of the following
|
||||||
|
* values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}.
|
||||||
|
* @param tag tag of this {@link Entry}.
|
||||||
|
* @param metered metered state of this {@link Entry}. Should be one of the following
|
||||||
|
* values: {link #METERED_YES}, {link #METERED_NO}.
|
||||||
|
* @param roaming roaming state of this {@link Entry}. Should be one of the following
|
||||||
|
* values: {link #ROAMING_YES}, {link #ROAMING_NO}.
|
||||||
|
* @param defaultNetwork default network status of this {@link Entry}. Should be one
|
||||||
|
* of the following values: {link #DEFAULT_NETWORK_YES},
|
||||||
|
* {link #DEFAULT_NETWORK_NO}.
|
||||||
|
* @param rxBytes Number of bytes received for this {@link Entry}. Statistics should
|
||||||
|
* represent the contents of IP packets, including IP headers.
|
||||||
|
* @param rxPackets Number of packets received for this {@link Entry}. Statistics should
|
||||||
|
* represent the contents of IP packets, including IP headers.
|
||||||
|
* @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should
|
||||||
|
* represent the contents of IP packets, including IP headers.
|
||||||
|
* @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should
|
||||||
|
* represent the contents of IP packets, including IP headers.
|
||||||
|
* @param operations count of network operations performed for this {@link Entry}. This can
|
||||||
|
* be used to derive bytes-per-operation.
|
||||||
|
*/
|
||||||
public Entry(@Nullable String iface, int uid, @State int set, int tag,
|
public Entry(@Nullable String iface, int uid, @State int set, int tag,
|
||||||
@Meteredness int metered, @Roaming int roaming, @DefaultNetwork int defaultNetwork,
|
@Meteredness int metered, @Roaming int roaming, @DefaultNetwork int defaultNetwork,
|
||||||
long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
|
long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
|
||||||
@@ -466,7 +503,7 @@ public final class NetworkStats implements Parcelable {
|
|||||||
NetworkStats.Entry entry = null;
|
NetworkStats.Entry entry = null;
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
entry = getValues(i, entry);
|
entry = getValues(i, entry);
|
||||||
clone.addEntry(entry);
|
clone.insertEntry(entry);
|
||||||
}
|
}
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
@@ -493,26 +530,26 @@ public final class NetworkStats implements Parcelable {
|
|||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public NetworkStats addIfaceValues(
|
public NetworkStats insertEntry(
|
||||||
String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
|
String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
|
||||||
return addEntry(
|
return insertEntry(
|
||||||
iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
|
iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public NetworkStats addEntry(String iface, int uid, int set, int tag, long rxBytes,
|
public NetworkStats insertEntry(String iface, int uid, int set, int tag, long rxBytes,
|
||||||
long rxPackets, long txBytes, long txPackets, long operations) {
|
long rxPackets, long txBytes, long txPackets, long operations) {
|
||||||
return addEntry(new Entry(
|
return insertEntry(new Entry(
|
||||||
iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
|
iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public NetworkStats addEntry(String iface, int uid, int set, int tag, int metered, int roaming,
|
public NetworkStats insertEntry(String iface, int uid, int set, int tag, int metered,
|
||||||
int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets,
|
int roaming, int defaultNetwork, long rxBytes, long rxPackets, long txBytes,
|
||||||
long operations) {
|
long txPackets, long operations) {
|
||||||
return addEntry(new Entry(
|
return insertEntry(new Entry(
|
||||||
iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets,
|
iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets,
|
||||||
txBytes, txPackets, operations));
|
txBytes, txPackets, operations));
|
||||||
}
|
}
|
||||||
@@ -522,7 +559,7 @@ public final class NetworkStats implements Parcelable {
|
|||||||
* object can be recycled across multiple calls.
|
* object can be recycled across multiple calls.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public NetworkStats addEntry(Entry entry) {
|
public NetworkStats insertEntry(Entry entry) {
|
||||||
if (size >= capacity) {
|
if (size >= capacity) {
|
||||||
final int newLength = Math.max(size, 10) * 3 / 2;
|
final int newLength = Math.max(size, 10) * 3 / 2;
|
||||||
iface = Arrays.copyOf(iface, newLength);
|
iface = Arrays.copyOf(iface, newLength);
|
||||||
@@ -665,7 +702,7 @@ public final class NetworkStats implements Parcelable {
|
|||||||
entry.roaming, entry.defaultNetwork);
|
entry.roaming, entry.defaultNetwork);
|
||||||
if (i == -1) {
|
if (i == -1) {
|
||||||
// only create new entry when positive contribution
|
// only create new entry when positive contribution
|
||||||
addEntry(entry);
|
insertEntry(entry);
|
||||||
} else {
|
} else {
|
||||||
rxBytes[i] += entry.rxBytes;
|
rxBytes[i] += entry.rxBytes;
|
||||||
rxPackets[i] += entry.rxPackets;
|
rxPackets[i] += entry.rxPackets;
|
||||||
@@ -684,7 +721,7 @@ public final class NetworkStats implements Parcelable {
|
|||||||
* @param entry the {@link Entry} to add.
|
* @param entry the {@link Entry} to add.
|
||||||
* @return a new constructed {@link NetworkStats} object that contains the result.
|
* @return a new constructed {@link NetworkStats} object that contains the result.
|
||||||
*/
|
*/
|
||||||
public @NonNull NetworkStats addValues(@NonNull Entry entry) {
|
public @NonNull NetworkStats addEntry(@NonNull Entry entry) {
|
||||||
return this.clone().combineValues(entry);
|
return this.clone().combineValues(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1003,7 +1040,7 @@ public final class NetworkStats implements Parcelable {
|
|||||||
entry.operations = Math.max(entry.operations, 0);
|
entry.operations = Math.max(entry.operations, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.addEntry(entry);
|
result.insertEntry(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ package android.net.netstats.provider;
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
oneway interface INetworkStatsProvider {
|
oneway interface INetworkStatsProvider {
|
||||||
void requestStatsUpdate(int token);
|
void onRequestStatsUpdate(int token);
|
||||||
void setLimit(String iface, long quotaBytes);
|
void onSetLimit(String iface, long quotaBytes);
|
||||||
void setAlert(long quotaBytes);
|
void onSetAlert(long quotaBytes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ import android.net.NetworkStats;
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
oneway interface INetworkStatsProviderCallback {
|
oneway interface INetworkStatsProviderCallback {
|
||||||
void onStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats);
|
void notifyStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats);
|
||||||
void onAlertReached();
|
void notifyAlertReached();
|
||||||
void onLimitReached();
|
void notifyLimitReached();
|
||||||
void unregister();
|
void unregister();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.netstats.provider;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.SystemApi;
|
||||||
|
import android.net.NetworkStats;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A base class that allows external modules to implement a custom network statistics provider.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
public abstract class NetworkStatsProvider {
|
||||||
|
/**
|
||||||
|
* A value used by {@link #onSetLimit} and {@link #onSetAlert} indicates there is no limit.
|
||||||
|
*/
|
||||||
|
public static final int QUOTA_UNLIMITED = -1;
|
||||||
|
|
||||||
|
@NonNull private final INetworkStatsProvider mProviderBinder =
|
||||||
|
new INetworkStatsProvider.Stub() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestStatsUpdate(int token) {
|
||||||
|
NetworkStatsProvider.this.onRequestStatsUpdate(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSetLimit(String iface, long quotaBytes) {
|
||||||
|
NetworkStatsProvider.this.onSetLimit(iface, quotaBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSetAlert(long quotaBytes) {
|
||||||
|
NetworkStatsProvider.this.onSetAlert(quotaBytes);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The binder given by the service when successfully registering. Only null before registering,
|
||||||
|
// never null once non-null.
|
||||||
|
@Nullable
|
||||||
|
private INetworkStatsProviderCallback mProviderCbBinder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the binder invoked by the service and redirect function calls to the overridden
|
||||||
|
* methods.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public INetworkStatsProvider getProviderBinder() {
|
||||||
|
return mProviderBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the binder that was returned by the service when successfully registering. Note that
|
||||||
|
* the provider cannot be re-registered. Hence this method can only be called once per provider.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void setProviderCallbackBinder(@NonNull INetworkStatsProviderCallback binder) {
|
||||||
|
if (mProviderCbBinder != null) {
|
||||||
|
throw new IllegalArgumentException("provider is already registered");
|
||||||
|
}
|
||||||
|
mProviderCbBinder = binder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the binder that was returned by the service when successfully registering. Or null if the
|
||||||
|
* provider was never registered.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public INetworkStatsProviderCallback getProviderCallbackBinder() {
|
||||||
|
return mProviderCbBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the binder that was returned by the service when successfully registering. Throw an
|
||||||
|
* {@link IllegalStateException} if the provider is not registered.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public INetworkStatsProviderCallback getProviderCallbackBinderOrThrow() {
|
||||||
|
if (mProviderCbBinder == null) {
|
||||||
|
throw new IllegalStateException("the provider is not registered");
|
||||||
|
}
|
||||||
|
return mProviderCbBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the system of new network statistics.
|
||||||
|
*
|
||||||
|
* Send the network statistics recorded since the last call to {@link #notifyStatsUpdated}. Must
|
||||||
|
* be called as soon as possible after {@link NetworkStatsProvider#onRequestStatsUpdate(int)}
|
||||||
|
* being called. Responding later increases the probability stats will be dropped. The
|
||||||
|
* provider can also call this whenever it wants to reports new stats for any reason.
|
||||||
|
* Note that the system will not necessarily immediately propagate the statistics to
|
||||||
|
* reflect the update.
|
||||||
|
*
|
||||||
|
* @param token the token under which these stats were gathered. Providers can call this method
|
||||||
|
* with the current token as often as they want, until the token changes.
|
||||||
|
* {@see NetworkStatsProvider#onRequestStatsUpdate()}
|
||||||
|
* @param ifaceStats the {@link NetworkStats} per interface to be reported.
|
||||||
|
* The provider should not include any traffic that is already counted by
|
||||||
|
* kernel interface counters.
|
||||||
|
* @param uidStats the same stats as above, but counts {@link NetworkStats}
|
||||||
|
* per uid.
|
||||||
|
*/
|
||||||
|
public void notifyStatsUpdated(int token, @NonNull NetworkStats ifaceStats,
|
||||||
|
@NonNull NetworkStats uidStats) {
|
||||||
|
try {
|
||||||
|
getProviderCallbackBinderOrThrow().notifyStatsUpdated(token, ifaceStats, uidStats);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowAsRuntimeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify system that the quota set by {@code onSetAlert} has been reached.
|
||||||
|
*/
|
||||||
|
public void notifyAlertReached() {
|
||||||
|
try {
|
||||||
|
getProviderCallbackBinderOrThrow().notifyAlertReached();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowAsRuntimeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify system that the quota set by {@code onSetLimit} has been reached.
|
||||||
|
*/
|
||||||
|
public void notifyLimitReached() {
|
||||||
|
try {
|
||||||
|
getProviderCallbackBinderOrThrow().notifyLimitReached();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowAsRuntimeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by {@code NetworkStatsService} when it requires to know updated stats.
|
||||||
|
* The provider MUST respond by calling {@link #notifyStatsUpdated} as soon as possible.
|
||||||
|
* Responding later increases the probability stats will be dropped. Memory allowing, the
|
||||||
|
* system will try to take stats into account up to one minute after calling
|
||||||
|
* {@link #onRequestStatsUpdate}.
|
||||||
|
*
|
||||||
|
* @param token a positive number identifying the new state of the system under which
|
||||||
|
* {@link NetworkStats} have to be gathered from now on. When this is called,
|
||||||
|
* custom implementations of providers MUST tally and report the latest stats with
|
||||||
|
* the previous token, under which stats were being gathered so far.
|
||||||
|
*/
|
||||||
|
public abstract void onRequestStatsUpdate(int token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by {@code NetworkStatsService} when setting the interface quota for the specified
|
||||||
|
* upstream interface. When this is called, the custom implementation should block all egress
|
||||||
|
* packets on the {@code iface} associated with the provider when {@code quotaBytes} bytes have
|
||||||
|
* been reached, and MUST respond to it by calling
|
||||||
|
* {@link NetworkStatsProvider#notifyLimitReached()}.
|
||||||
|
*
|
||||||
|
* @param iface the interface requiring the operation.
|
||||||
|
* @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
|
||||||
|
* from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit.
|
||||||
|
*/
|
||||||
|
public abstract void onSetLimit(@NonNull String iface, long quotaBytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations
|
||||||
|
* MUST call {@link NetworkStatsProvider#notifyAlertReached()} when {@code quotaBytes} bytes
|
||||||
|
* have been reached. Unlike {@link #onSetLimit(String, long)}, the custom implementation should
|
||||||
|
* not block all egress packets.
|
||||||
|
*
|
||||||
|
* @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
|
||||||
|
* from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no alert.
|
||||||
|
*/
|
||||||
|
public abstract void onSetAlert(long quotaBytes);
|
||||||
|
}
|
||||||
@@ -229,7 +229,7 @@ public class NetworkStatsFactory {
|
|||||||
entry.txPackets += reader.nextLong();
|
entry.txPackets += reader.nextLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.addEntry(entry);
|
stats.insertEntry(entry);
|
||||||
reader.finishLine();
|
reader.finishLine();
|
||||||
}
|
}
|
||||||
} catch (NullPointerException|NumberFormatException e) {
|
} catch (NullPointerException|NumberFormatException e) {
|
||||||
@@ -279,7 +279,7 @@ public class NetworkStatsFactory {
|
|||||||
entry.txBytes = reader.nextLong();
|
entry.txBytes = reader.nextLong();
|
||||||
entry.txPackets = reader.nextLong();
|
entry.txPackets = reader.nextLong();
|
||||||
|
|
||||||
stats.addEntry(entry);
|
stats.insertEntry(entry);
|
||||||
reader.finishLine();
|
reader.finishLine();
|
||||||
}
|
}
|
||||||
} catch (NullPointerException|NumberFormatException e) {
|
} catch (NullPointerException|NumberFormatException e) {
|
||||||
@@ -439,7 +439,7 @@ public class NetworkStatsFactory {
|
|||||||
if ((limitIfaces == null || ArrayUtils.contains(limitIfaces, entry.iface))
|
if ((limitIfaces == null || ArrayUtils.contains(limitIfaces, entry.iface))
|
||||||
&& (limitUid == UID_ALL || limitUid == entry.uid)
|
&& (limitUid == UID_ALL || limitUid == entry.uid)
|
||||||
&& (limitTag == TAG_ALL || limitTag == entry.tag)) {
|
&& (limitTag == TAG_ALL || limitTag == entry.tag)) {
|
||||||
stats.addEntry(entry);
|
stats.insertEntry(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.finishLine();
|
reader.finishLine();
|
||||||
|
|||||||
@@ -17,12 +17,14 @@
|
|||||||
package com.android.server.net;
|
package com.android.server.net;
|
||||||
|
|
||||||
import static android.Manifest.permission.ACCESS_NETWORK_STATE;
|
import static android.Manifest.permission.ACCESS_NETWORK_STATE;
|
||||||
|
import static android.Manifest.permission.NETWORK_STATS_PROVIDER;
|
||||||
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
|
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
|
||||||
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
|
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
|
||||||
import static android.content.Intent.ACTION_SHUTDOWN;
|
import static android.content.Intent.ACTION_SHUTDOWN;
|
||||||
import static android.content.Intent.ACTION_UID_REMOVED;
|
import static android.content.Intent.ACTION_UID_REMOVED;
|
||||||
import static android.content.Intent.ACTION_USER_REMOVED;
|
import static android.content.Intent.ACTION_USER_REMOVED;
|
||||||
import static android.content.Intent.EXTRA_UID;
|
import static android.content.Intent.EXTRA_UID;
|
||||||
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
|
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
|
||||||
import static android.net.ConnectivityManager.isNetworkTypeMobile;
|
import static android.net.ConnectivityManager.isNetworkTypeMobile;
|
||||||
import static android.net.NetworkStack.checkNetworkStackPermission;
|
import static android.net.NetworkStack.checkNetworkStackPermission;
|
||||||
@@ -101,7 +103,7 @@ import android.net.NetworkTemplate;
|
|||||||
import android.net.TrafficStats;
|
import android.net.TrafficStats;
|
||||||
import android.net.netstats.provider.INetworkStatsProvider;
|
import android.net.netstats.provider.INetworkStatsProvider;
|
||||||
import android.net.netstats.provider.INetworkStatsProviderCallback;
|
import android.net.netstats.provider.INetworkStatsProviderCallback;
|
||||||
import android.net.netstats.provider.NetworkStatsProviderCallback;
|
import android.net.netstats.provider.NetworkStatsProvider;
|
||||||
import android.os.BestClock;
|
import android.os.BestClock;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.DropBoxManager;
|
import android.os.DropBoxManager;
|
||||||
@@ -556,7 +558,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// ignored; service lives in system_server
|
// ignored; service lives in system_server
|
||||||
}
|
}
|
||||||
invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setAlert(mGlobalAlertBytes));
|
invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetAlert(mGlobalAlertBytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -757,7 +759,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
|
final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
|
||||||
|
|
||||||
final NetworkStats stats = new NetworkStats(end - start, 1);
|
final NetworkStats stats = new NetworkStats(end - start, 1);
|
||||||
stats.addEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
|
stats.insertEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
|
||||||
METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets,
|
METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets,
|
||||||
entry.txBytes, entry.txPackets, entry.operations));
|
entry.txBytes, entry.txPackets, entry.operations));
|
||||||
return stats;
|
return stats;
|
||||||
@@ -1374,7 +1376,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate");
|
Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate");
|
||||||
final int registeredCallbackCount = mStatsProviderCbList.getRegisteredCallbackCount();
|
final int registeredCallbackCount = mStatsProviderCbList.getRegisteredCallbackCount();
|
||||||
mStatsProviderSem.drainPermits();
|
mStatsProviderSem.drainPermits();
|
||||||
invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.requestStatsUpdate(0 /* unused */));
|
invokeForAllStatsProviderCallbacks(
|
||||||
|
(cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */));
|
||||||
try {
|
try {
|
||||||
mStatsProviderSem.tryAcquire(registeredCallbackCount,
|
mStatsProviderSem.tryAcquire(registeredCallbackCount,
|
||||||
MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS);
|
MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS);
|
||||||
@@ -1549,7 +1552,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void setStatsProviderLimitAsync(@NonNull String iface, long quota) {
|
public void setStatsProviderLimitAsync(@NonNull String iface, long quota) {
|
||||||
Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")");
|
Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")");
|
||||||
invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setLimit(iface, quota));
|
invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetLimit(iface, quota));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1793,6 +1796,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: It is copied from ConnectivityService, consider refactor these check permission
|
||||||
|
// functions to a proper util.
|
||||||
|
private boolean checkAnyPermissionOf(String... permissions) {
|
||||||
|
for (String permission : permissions) {
|
||||||
|
if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enforceAnyPermissionOf(String... permissions) {
|
||||||
|
if (!checkAnyPermissionOf(permissions)) {
|
||||||
|
throw new SecurityException("Requires one of the following permissions: "
|
||||||
|
+ String.join(", ", permissions) + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a custom provider of {@link android.net.NetworkStats} to combine the network
|
* Registers a custom provider of {@link android.net.NetworkStats} to combine the network
|
||||||
* statistics that cannot be seen by the kernel to system. To unregister, invoke the
|
* statistics that cannot be seen by the kernel to system. To unregister, invoke the
|
||||||
@@ -1800,16 +1821,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
*
|
*
|
||||||
* @param tag a human readable identifier of the custom network stats provider.
|
* @param tag a human readable identifier of the custom network stats provider.
|
||||||
* @param provider the {@link INetworkStatsProvider} binder corresponding to the
|
* @param provider the {@link INetworkStatsProvider} binder corresponding to the
|
||||||
* {@link android.net.netstats.provider.AbstractNetworkStatsProvider} to be
|
* {@link NetworkStatsProvider} to be registered.
|
||||||
* registered.
|
|
||||||
*
|
*
|
||||||
* @return a binder interface of
|
* @return a {@link INetworkStatsProviderCallback} binder
|
||||||
* {@link android.net.netstats.provider.NetworkStatsProviderCallback}, which can be
|
* interface, which can be used to report events to the system.
|
||||||
* used to report events to the system.
|
|
||||||
*/
|
*/
|
||||||
public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider(
|
public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider(
|
||||||
@NonNull String tag, @NonNull INetworkStatsProvider provider) {
|
@NonNull String tag, @NonNull INetworkStatsProvider provider) {
|
||||||
mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG);
|
enforceAnyPermissionOf(NETWORK_STATS_PROVIDER,
|
||||||
|
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
|
||||||
Objects.requireNonNull(provider, "provider is null");
|
Objects.requireNonNull(provider, "provider is null");
|
||||||
Objects.requireNonNull(tag, "tag is null");
|
Objects.requireNonNull(tag, "tag is null");
|
||||||
try {
|
try {
|
||||||
@@ -1910,7 +1930,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStatsUpdated(int token, @Nullable NetworkStats ifaceStats,
|
public void notifyStatsUpdated(int token, @Nullable NetworkStats ifaceStats,
|
||||||
@Nullable NetworkStats uidStats) {
|
@Nullable NetworkStats uidStats) {
|
||||||
// TODO: 1. Use token to map ifaces to correct NetworkIdentity.
|
// TODO: 1. Use token to map ifaces to correct NetworkIdentity.
|
||||||
// 2. Store the difference and store it directly to the recorder.
|
// 2. Store the difference and store it directly to the recorder.
|
||||||
@@ -1922,12 +1942,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAlertReached() throws RemoteException {
|
public void notifyAlertReached() throws RemoteException {
|
||||||
mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */);
|
mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLimitReached() {
|
public void notifyLimitReached() {
|
||||||
Log.d(TAG, mTag + ": onLimitReached");
|
Log.d(TAG, mTag + ": onLimitReached");
|
||||||
LocalServices.getService(NetworkPolicyManagerInternal.class)
|
LocalServices.getService(NetworkPolicyManagerInternal.class)
|
||||||
.onStatsProviderLimitReached(mTag);
|
.onStatsProviderLimitReached(mTag);
|
||||||
|
|||||||
Reference in New Issue
Block a user