Merge changes I7eaca623,Ic94da540,If330e853,Ie2d229be,Ic6b2f10f
* changes: [SM08] Add NetworkTemplate unit test for fetching mobile data usage [SM07] Make combine subtype configurable from Settings [SM05] Enable record mobile network stats by collapsed rat type [SM04] Support fetching data with NetworkTemplate with subType [SM02] Support record mobile network stats by collapsed rat type
This commit is contained in:
@@ -25,6 +25,7 @@ import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build;
|
||||
import android.service.NetworkIdentityProto;
|
||||
import android.telephony.Annotation.NetworkType;
|
||||
import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
@@ -39,16 +40,6 @@ import java.util.Objects;
|
||||
public class NetworkIdentity implements Comparable<NetworkIdentity> {
|
||||
private static final String TAG = "NetworkIdentity";
|
||||
|
||||
/**
|
||||
* When enabled, combine all {@link #mSubType} together under
|
||||
* {@link #SUBTYPE_COMBINED}.
|
||||
*
|
||||
* @deprecated we no longer offer to collect statistics on a per-subtype
|
||||
* basis; this is always disabled.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final boolean COMBINE_SUBTYPE_ENABLED = true;
|
||||
|
||||
public static final int SUBTYPE_COMBINED = -1;
|
||||
|
||||
final int mType;
|
||||
@@ -63,7 +54,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
|
||||
int type, int subType, String subscriberId, String networkId, boolean roaming,
|
||||
boolean metered, boolean defaultNetwork) {
|
||||
mType = type;
|
||||
mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
|
||||
mSubType = subType;
|
||||
mSubscriberId = subscriberId;
|
||||
mNetworkId = networkId;
|
||||
mRoaming = roaming;
|
||||
@@ -95,7 +86,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
|
||||
final StringBuilder builder = new StringBuilder("{");
|
||||
builder.append("type=").append(getNetworkTypeName(mType));
|
||||
builder.append(", subType=");
|
||||
if (COMBINE_SUBTYPE_ENABLED) {
|
||||
if (mSubType == SUBTYPE_COMBINED) {
|
||||
builder.append("COMBINED");
|
||||
} else {
|
||||
builder.append(mSubType);
|
||||
@@ -187,13 +178,14 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link NetworkIdentity} from the given {@link NetworkState},
|
||||
* assuming that any mobile networks are using the current IMSI.
|
||||
* Build a {@link NetworkIdentity} from the given {@link NetworkState} and {@code subType},
|
||||
* assuming that any mobile networks are using the current IMSI. The subType if applicable,
|
||||
* should be set as one of the TelephonyManager.NETWORK_TYPE_* constants, or
|
||||
* {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not.
|
||||
*/
|
||||
public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state,
|
||||
boolean defaultNetwork) {
|
||||
boolean defaultNetwork, @NetworkType int subType) {
|
||||
final int type = state.networkInfo.getType();
|
||||
final int subType = state.networkInfo.getSubtype();
|
||||
|
||||
String subscriberId = null;
|
||||
String networkId = null;
|
||||
|
||||
@@ -34,9 +34,13 @@ import static android.net.NetworkStats.ROAMING_NO;
|
||||
import static android.net.NetworkStats.ROAMING_YES;
|
||||
import static android.net.wifi.WifiInfo.sanitizeSsid;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.telephony.Annotation.NetworkType;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.BackupUtils;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -73,6 +77,14 @@ public class NetworkTemplate implements Parcelable {
|
||||
public static final int MATCH_BLUETOOTH = 8;
|
||||
public static final int MATCH_PROXY = 9;
|
||||
|
||||
/**
|
||||
* Include all network types when filtering. This is meant to merge in with the
|
||||
* {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int NETWORK_TYPE_ALL = -1;
|
||||
|
||||
private static boolean isKnownMatchRule(final int rule) {
|
||||
switch (rule) {
|
||||
case MATCH_MOBILE:
|
||||
@@ -117,7 +129,22 @@ public class NetworkTemplate implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Template to match {@link ConnectivityManager#TYPE_MOBILE} networks,
|
||||
* Template to match cellular networks with the given IMSI and {@code ratType}.
|
||||
* Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering.
|
||||
* See {@code TelephonyManager.NETWORK_TYPE_*}.
|
||||
*/
|
||||
public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
|
||||
@NetworkType int ratType) {
|
||||
if (TextUtils.isEmpty(subscriberId)) {
|
||||
return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null,
|
||||
METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType);
|
||||
}
|
||||
return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null,
|
||||
METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks,
|
||||
* regardless of IMSI.
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
@@ -126,7 +153,7 @@ public class NetworkTemplate implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
|
||||
* Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks,
|
||||
* regardless of SSID.
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
@@ -192,6 +219,7 @@ public class NetworkTemplate implements Parcelable {
|
||||
private final int mMetered;
|
||||
private final int mRoaming;
|
||||
private final int mDefaultNetwork;
|
||||
private final int mSubType;
|
||||
|
||||
@UnsupportedAppUsage
|
||||
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
|
||||
@@ -201,11 +229,11 @@ public class NetworkTemplate implements Parcelable {
|
||||
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
|
||||
String networkId) {
|
||||
this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL,
|
||||
DEFAULT_NETWORK_ALL);
|
||||
DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL);
|
||||
}
|
||||
|
||||
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
|
||||
String networkId, int metered, int roaming, int defaultNetwork) {
|
||||
String networkId, int metered, int roaming, int defaultNetwork, int subType) {
|
||||
mMatchRule = matchRule;
|
||||
mSubscriberId = subscriberId;
|
||||
mMatchSubscriberIds = matchSubscriberIds;
|
||||
@@ -213,6 +241,7 @@ public class NetworkTemplate implements Parcelable {
|
||||
mMetered = metered;
|
||||
mRoaming = roaming;
|
||||
mDefaultNetwork = defaultNetwork;
|
||||
mSubType = subType;
|
||||
|
||||
if (!isKnownMatchRule(matchRule)) {
|
||||
Log.e(TAG, "Unknown network template rule " + matchRule
|
||||
@@ -228,6 +257,7 @@ public class NetworkTemplate implements Parcelable {
|
||||
mMetered = in.readInt();
|
||||
mRoaming = in.readInt();
|
||||
mDefaultNetwork = in.readInt();
|
||||
mSubType = in.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -239,6 +269,7 @@ public class NetworkTemplate implements Parcelable {
|
||||
dest.writeInt(mMetered);
|
||||
dest.writeInt(mRoaming);
|
||||
dest.writeInt(mDefaultNetwork);
|
||||
dest.writeInt(mSubType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -271,13 +302,16 @@ public class NetworkTemplate implements Parcelable {
|
||||
builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString(
|
||||
mDefaultNetwork));
|
||||
}
|
||||
if (mSubType != NETWORK_TYPE_ALL) {
|
||||
builder.append(", subType=").append(mSubType);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming,
|
||||
mDefaultNetwork);
|
||||
mDefaultNetwork, mSubType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -289,7 +323,8 @@ public class NetworkTemplate implements Parcelable {
|
||||
&& Objects.equals(mNetworkId, other.mNetworkId)
|
||||
&& mMetered == other.mMetered
|
||||
&& mRoaming == other.mRoaming
|
||||
&& mDefaultNetwork == other.mDefaultNetwork;
|
||||
&& mDefaultNetwork == other.mDefaultNetwork
|
||||
&& mSubType == other.mSubType;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -376,6 +411,11 @@ public class NetworkTemplate implements Parcelable {
|
||||
|| (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork);
|
||||
}
|
||||
|
||||
private boolean matchesCollapsedRatType(NetworkIdentity ident) {
|
||||
return mSubType == NETWORK_TYPE_ALL
|
||||
|| getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType);
|
||||
}
|
||||
|
||||
public boolean matchesSubscriberId(String subscriberId) {
|
||||
return ArrayUtils.contains(mMatchSubscriberIds, subscriberId);
|
||||
}
|
||||
@@ -388,9 +428,52 @@ public class NetworkTemplate implements Parcelable {
|
||||
// TODO: consider matching against WiMAX subscriber identity
|
||||
return true;
|
||||
} else {
|
||||
// Only metered mobile network would be matched regardless of metered filter.
|
||||
// This is used to exclude non-metered APNs, e.g. IMS. See ag/908650.
|
||||
// TODO: Respect metered filter and remove mMetered condition.
|
||||
return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
|
||||
&& !ArrayUtils.isEmpty(mMatchSubscriberIds)
|
||||
&& ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
|
||||
&& ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
|
||||
&& matchesCollapsedRatType(ident);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Radio Access Technology(RAT) type that is representative of a group of RAT types.
|
||||
* The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}.
|
||||
*
|
||||
* @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
|
||||
*/
|
||||
// TODO: 1. Consider move this to TelephonyManager if used by other modules.
|
||||
// 2. Consider make this configurable.
|
||||
// 3. Use TelephonyManager APIs when available.
|
||||
public static int getCollapsedRatType(int ratType) {
|
||||
switch (ratType) {
|
||||
case TelephonyManager.NETWORK_TYPE_GPRS:
|
||||
case TelephonyManager.NETWORK_TYPE_GSM:
|
||||
case TelephonyManager.NETWORK_TYPE_EDGE:
|
||||
case TelephonyManager.NETWORK_TYPE_IDEN:
|
||||
case TelephonyManager.NETWORK_TYPE_CDMA:
|
||||
case TelephonyManager.NETWORK_TYPE_1xRTT:
|
||||
return TelephonyManager.NETWORK_TYPE_GSM;
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_0:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_A:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_B:
|
||||
case TelephonyManager.NETWORK_TYPE_EHRPD:
|
||||
case TelephonyManager.NETWORK_TYPE_UMTS:
|
||||
case TelephonyManager.NETWORK_TYPE_HSDPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSUPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSPAP:
|
||||
case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
|
||||
return TelephonyManager.NETWORK_TYPE_UMTS;
|
||||
case TelephonyManager.NETWORK_TYPE_LTE:
|
||||
case TelephonyManager.NETWORK_TYPE_IWLAN:
|
||||
return TelephonyManager.NETWORK_TYPE_LTE;
|
||||
case TelephonyManager.NETWORK_TYPE_NR:
|
||||
return TelephonyManager.NETWORK_TYPE_NR;
|
||||
default:
|
||||
return TelephonyManager.NETWORK_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,7 +504,8 @@ public class NetworkTemplate implements Parcelable {
|
||||
if (ident.mType == TYPE_WIMAX) {
|
||||
return true;
|
||||
} else {
|
||||
return sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered);
|
||||
return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
|
||||
&& matchesCollapsedRatType(ident);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10197,6 +10197,8 @@ public final class Settings {
|
||||
public static final String NETSTATS_SAMPLE_ENABLED = "netstats_sample_enabled";
|
||||
/** {@hide} */
|
||||
public static final String NETSTATS_AUGMENT_ENABLED = "netstats_augment_enabled";
|
||||
/** {@hide} */
|
||||
public static final String NETSTATS_COMBINE_SUBTYPE_ENABLED = "netstats_combine_subtype_enabled";
|
||||
|
||||
/** {@hide} */
|
||||
public static final String NETSTATS_DEV_BUCKET_DURATION = "netstats_dev_bucket_duration";
|
||||
|
||||
@@ -346,6 +346,7 @@ public class SettingsBackupTest {
|
||||
Settings.Global.NETSTATS_POLL_INTERVAL,
|
||||
Settings.Global.NETSTATS_SAMPLE_ENABLED,
|
||||
Settings.Global.NETSTATS_AUGMENT_ENABLED,
|
||||
Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED,
|
||||
Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE,
|
||||
Settings.Global.NETSTATS_UID_BUCKET_DURATION,
|
||||
Settings.Global.NETSTATS_UID_DELETE_AGE,
|
||||
|
||||
@@ -25,6 +25,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||
import static android.net.NetworkPolicy.LIMIT_DISABLED;
|
||||
import static android.net.NetworkPolicy.WARNING_DISABLED;
|
||||
import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
|
||||
import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES;
|
||||
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
|
||||
@@ -220,7 +221,7 @@ public class MultipathPolicyTracker {
|
||||
mNetworkTemplate = new NetworkTemplate(
|
||||
NetworkTemplate.MATCH_MOBILE, subscriberId, new String[] { subscriberId },
|
||||
null, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
|
||||
NetworkStats.DEFAULT_NETWORK_NO);
|
||||
NetworkStats.DEFAULT_NETWORK_NO, NETWORK_TYPE_ALL);
|
||||
mUsageCallback = new UsageCallback() {
|
||||
@Override
|
||||
public void onThresholdReached(int networkType, String subscriberId) {
|
||||
|
||||
@@ -1869,8 +1869,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
mNetIdToSubId.put(state.network.netId, parseSubId(state));
|
||||
}
|
||||
if (state.networkInfo != null && state.networkInfo.isConnected()) {
|
||||
// Policies matched by NPMS only match by subscriber ID or by ssid. Thus subtype
|
||||
// in the object created here is never used and its value doesn't matter, so use
|
||||
// NETWORK_TYPE_UNKNOWN.
|
||||
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state,
|
||||
true);
|
||||
true, TelephonyManager.NETWORK_TYPE_UNKNOWN /* subType */);
|
||||
identified.put(state, ident);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ 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.isNetworkTypeMobile;
|
||||
import static android.net.NetworkIdentity.SUBTYPE_COMBINED;
|
||||
import static android.net.NetworkStack.checkNetworkStackPermission;
|
||||
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
|
||||
import static android.net.NetworkStats.IFACE_ALL;
|
||||
@@ -45,10 +46,12 @@ import static android.net.NetworkStats.UID_ALL;
|
||||
import static android.net.NetworkStatsHistory.FIELD_ALL;
|
||||
import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
|
||||
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
|
||||
import static android.net.NetworkTemplate.getCollapsedRatType;
|
||||
import static android.net.TrafficStats.KB_IN_BYTES;
|
||||
import static android.net.TrafficStats.MB_IN_BYTES;
|
||||
import static android.os.Trace.TRACE_TAG_NETWORK;
|
||||
import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED;
|
||||
import static android.provider.Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED;
|
||||
import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
|
||||
import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
|
||||
import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES;
|
||||
@@ -64,6 +67,9 @@ import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION;
|
||||
import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
|
||||
import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
|
||||
import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
|
||||
import static android.telephony.PhoneStateListener.LISTEN_NONE;
|
||||
import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE;
|
||||
import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
|
||||
import static android.text.format.DateUtils.DAY_IN_MILLIS;
|
||||
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
|
||||
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
|
||||
@@ -109,6 +115,7 @@ import android.os.Binder;
|
||||
import android.os.DropBoxManager;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerExecutor;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.INetworkManagementService;
|
||||
@@ -125,6 +132,8 @@ import android.provider.Settings;
|
||||
import android.provider.Settings.Global;
|
||||
import android.service.NetworkInterfaceProto;
|
||||
import android.service.NetworkStatsServiceDumpProto;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SubscriptionPlan;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.format.DateUtils;
|
||||
@@ -157,6 +166,7 @@ import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -173,6 +183,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
private static final int MSG_PERFORM_POLL = 1;
|
||||
// Perform polling, persist network, and register the global alert again.
|
||||
private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2;
|
||||
private static final int MSG_UPDATE_IFACES = 3;
|
||||
|
||||
/** Flags to control detail level of poll event. */
|
||||
private static final int FLAG_PERSIST_NETWORK = 0x1;
|
||||
@@ -229,12 +240,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
* Settings that can be changed externally.
|
||||
*/
|
||||
public interface NetworkStatsSettings {
|
||||
public long getPollInterval();
|
||||
public long getPollDelay();
|
||||
public boolean getSampleEnabled();
|
||||
public boolean getAugmentEnabled();
|
||||
long getPollInterval();
|
||||
long getPollDelay();
|
||||
boolean getSampleEnabled();
|
||||
boolean getAugmentEnabled();
|
||||
/**
|
||||
* When enabled, all mobile data is reported under {@link NetworkIdentity#SUBTYPE_COMBINED}.
|
||||
* When disabled, mobile data is broken down by a granular subtype representative of the
|
||||
* actual subtype. {@see NetworkTemplate#getCollapsedRatType}.
|
||||
* Enabling this decreases the level of detail but saves performance, disk space and
|
||||
* amount of data logged.
|
||||
*/
|
||||
boolean getCombineSubtypeEnabled();
|
||||
|
||||
public static class Config {
|
||||
class Config {
|
||||
public final long bucketDuration;
|
||||
public final long rotateAgeMillis;
|
||||
public final long deleteAgeMillis;
|
||||
@@ -246,16 +265,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
public Config getDevConfig();
|
||||
public Config getXtConfig();
|
||||
public Config getUidConfig();
|
||||
public Config getUidTagConfig();
|
||||
Config getDevConfig();
|
||||
Config getXtConfig();
|
||||
Config getUidConfig();
|
||||
Config getUidTagConfig();
|
||||
|
||||
public long getGlobalAlertBytes(long def);
|
||||
public long getDevPersistBytes(long def);
|
||||
public long getXtPersistBytes(long def);
|
||||
public long getUidPersistBytes(long def);
|
||||
public long getUidTagPersistBytes(long def);
|
||||
long getGlobalAlertBytes(long def);
|
||||
long getDevPersistBytes(long def);
|
||||
long getXtPersistBytes(long def);
|
||||
long getUidPersistBytes(long def);
|
||||
long getUidTagPersistBytes(long def);
|
||||
}
|
||||
|
||||
private final Object mStatsLock = new Object();
|
||||
@@ -280,6 +299,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
@GuardedBy("mStatsLock")
|
||||
private Network[] mDefaultNetworks = new Network[0];
|
||||
|
||||
/** Last states of all networks sent from ConnectivityService. */
|
||||
@GuardedBy("mStatsLock")
|
||||
@Nullable
|
||||
private NetworkState[] mLastNetworkStates = null;
|
||||
|
||||
private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
|
||||
new DropBoxNonMonotonicObserver();
|
||||
|
||||
@@ -355,6 +379,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
performPoll(FLAG_PERSIST_ALL);
|
||||
break;
|
||||
}
|
||||
case MSG_UPDATE_IFACES: {
|
||||
// If no cached states, ignore.
|
||||
if (mLastNetworkStates == null) break;
|
||||
updateIfaces(mDefaultNetworks, mLastNetworkStates, mActiveIface);
|
||||
break;
|
||||
}
|
||||
case MSG_PERFORM_POLL_REGISTER_ALERT: {
|
||||
performPoll(FLAG_PERSIST_NETWORK);
|
||||
registerGlobalAlert();
|
||||
@@ -407,6 +437,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
final HandlerThread handlerThread = mDeps.makeHandlerThread();
|
||||
handlerThread.start();
|
||||
mHandler = new NetworkStatsHandler(handlerThread.getLooper());
|
||||
mPhoneListener = new NetworkTypeListener(new HandlerExecutor(mHandler));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -486,6 +517,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
|
||||
mSettings.getPollInterval(), pollIntent);
|
||||
|
||||
// TODO: 1. listen to changes from all subscriptions.
|
||||
// 2. listen to settings changed to support dynamically enable/disable.
|
||||
// watch for networkType changes
|
||||
if (!mSettings.getCombineSubtypeEnabled()) {
|
||||
mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE);
|
||||
}
|
||||
|
||||
registerGlobalAlert();
|
||||
}
|
||||
|
||||
@@ -506,6 +544,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
mContext.unregisterReceiver(mUserReceiver);
|
||||
mContext.unregisterReceiver(mShutdownReceiver);
|
||||
|
||||
mTeleManager.listen(mPhoneListener, LISTEN_NONE);
|
||||
|
||||
final long currentTime = mClock.millis();
|
||||
|
||||
// persist any pending stats
|
||||
@@ -1156,6 +1196,38 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Receiver that watches for {@link TelephonyManager} changes, such as
|
||||
* transitioning between Radio Access Technology(RAT) types.
|
||||
*/
|
||||
@NonNull
|
||||
private final NetworkTypeListener mPhoneListener;
|
||||
|
||||
class NetworkTypeListener extends PhoneStateListener {
|
||||
private volatile int mLastCollapsedRatType = NETWORK_TYPE_UNKNOWN;
|
||||
|
||||
NetworkTypeListener(@NonNull Executor executor) {
|
||||
super(executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceStateChanged(@NonNull ServiceState ss) {
|
||||
final int networkType = ss.getDataNetworkType();
|
||||
final int collapsedRatType = getCollapsedRatType(networkType);
|
||||
if (collapsedRatType == mLastCollapsedRatType) return;
|
||||
|
||||
if (LOGD) {
|
||||
Log.d(TAG, "subtype changed for mobile: "
|
||||
+ mLastCollapsedRatType + " -> " + collapsedRatType);
|
||||
}
|
||||
// Protect service from frequently updating. Remove pending messages if any.
|
||||
mHandler.removeMessages(MSG_UPDATE_IFACES);
|
||||
mLastCollapsedRatType = collapsedRatType;
|
||||
mHandler.sendMessageDelayed(
|
||||
mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateIfaces(
|
||||
Network[] defaultNetworks,
|
||||
NetworkState[] networkStates,
|
||||
@@ -1177,7 +1249,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
* they are combined under a single {@link NetworkIdentitySet}.
|
||||
*/
|
||||
@GuardedBy("mStatsLock")
|
||||
private void updateIfacesLocked(Network[] defaultNetworks, NetworkState[] states) {
|
||||
private void updateIfacesLocked(@Nullable Network[] defaultNetworks,
|
||||
@NonNull NetworkState[] states) {
|
||||
if (!mSystemReady) return;
|
||||
if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
|
||||
|
||||
@@ -1197,13 +1270,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
mDefaultNetworks = defaultNetworks;
|
||||
}
|
||||
|
||||
mLastNetworkStates = states;
|
||||
|
||||
final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled();
|
||||
final ArraySet<String> mobileIfaces = new ArraySet<>();
|
||||
for (NetworkState state : states) {
|
||||
if (state.networkInfo.isConnected()) {
|
||||
final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType());
|
||||
final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network);
|
||||
final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED
|
||||
: getSubTypeForState(state);
|
||||
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state,
|
||||
isDefault);
|
||||
isDefault, subType);
|
||||
|
||||
// Traffic occurring on the base interface is always counted for
|
||||
// both total usage and UID details.
|
||||
@@ -1264,6 +1342,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through
|
||||
* {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different
|
||||
* transport types do not actually fill this value.
|
||||
*/
|
||||
private int getSubTypeForState(@NonNull NetworkState state) {
|
||||
if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: return different subType for different subscriptions.
|
||||
return mPhoneListener.mLastCollapsedRatType;
|
||||
}
|
||||
|
||||
private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet(
|
||||
ArrayMap<K, NetworkIdentitySet> map, K key) {
|
||||
NetworkIdentitySet ident = map.get(key);
|
||||
@@ -1617,6 +1709,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
return;
|
||||
}
|
||||
|
||||
pw.println("Configs:");
|
||||
pw.increaseIndent();
|
||||
pw.printPair(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled());
|
||||
pw.println();
|
||||
pw.decreaseIndent();
|
||||
|
||||
pw.println("Active interfaces:");
|
||||
pw.increaseIndent();
|
||||
for (int i = 0; i < mActiveIfaces.size(); i++) {
|
||||
@@ -2045,6 +2143,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true);
|
||||
}
|
||||
@Override
|
||||
public boolean getCombineSubtypeEnabled() {
|
||||
return getGlobalBoolean(NETSTATS_COMBINE_SUBTYPE_ENABLED, false);
|
||||
}
|
||||
@Override
|
||||
public Config getDevConfig() {
|
||||
return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
|
||||
getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
|
||||
|
||||
155
tests/net/java/android/net/NetworkTemplateTest.kt
Normal file
155
tests/net/java/android/net/NetworkTemplateTest.kt
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager.TYPE_MOBILE
|
||||
import android.net.ConnectivityManager.TYPE_WIFI
|
||||
import android.net.NetworkIdentity.SUBTYPE_COMBINED
|
||||
import android.net.NetworkIdentity.buildNetworkIdentity
|
||||
import android.net.NetworkStats.DEFAULT_NETWORK_ALL
|
||||
import android.net.NetworkStats.METERED_ALL
|
||||
import android.net.NetworkStats.ROAMING_ALL
|
||||
import android.net.NetworkTemplate.MATCH_MOBILE
|
||||
import android.net.NetworkTemplate.MATCH_WIFI
|
||||
import android.net.NetworkTemplate.NETWORK_TYPE_ALL
|
||||
import android.net.NetworkTemplate.buildTemplateMobileWithRatType
|
||||
import android.telephony.TelephonyManager
|
||||
import com.android.testutils.assertParcelSane
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
import org.mockito.Mockito.doReturn
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
private const val TEST_IMSI1 = "imsi1"
|
||||
private const val TEST_IMSI2 = "imsi2"
|
||||
private const val TEST_SSID1 = "ssid1"
|
||||
|
||||
@RunWith(JUnit4::class)
|
||||
class NetworkTemplateTest {
|
||||
private val mockContext = mock(Context::class.java)
|
||||
|
||||
private fun buildMobileNetworkState(subscriberId: String): NetworkState =
|
||||
buildNetworkState(TYPE_MOBILE, subscriberId = subscriberId)
|
||||
private fun buildWifiNetworkState(ssid: String): NetworkState =
|
||||
buildNetworkState(TYPE_WIFI, ssid = ssid)
|
||||
|
||||
private fun buildNetworkState(
|
||||
type: Int,
|
||||
subscriberId: String? = null,
|
||||
ssid: String? = null
|
||||
): NetworkState {
|
||||
val info = mock(NetworkInfo::class.java)
|
||||
doReturn(type).`when`(info).type
|
||||
doReturn(NetworkInfo.State.CONNECTED).`when`(info).state
|
||||
val lp = LinkProperties()
|
||||
val caps = NetworkCapabilities().apply {
|
||||
setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false)
|
||||
setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true)
|
||||
}
|
||||
return NetworkState(info, lp, caps, mock(Network::class.java), subscriberId, ssid)
|
||||
}
|
||||
|
||||
private fun NetworkTemplate.assertMatches(ident: NetworkIdentity) =
|
||||
assertTrue(matches(ident), "$this does not match $ident")
|
||||
|
||||
private fun NetworkTemplate.assertDoesNotMatch(ident: NetworkIdentity) =
|
||||
assertFalse(matches(ident), "$this should match $ident")
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRatTypeGroupMatches() {
|
||||
val stateMobile = buildMobileNetworkState(TEST_IMSI1)
|
||||
// Build UMTS template that matches mobile identities with RAT in the same
|
||||
// group with any IMSI. See {@link NetworkTemplate#getCollapsedRatType}.
|
||||
val templateUmts = buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS)
|
||||
// Build normal template that matches mobile identities with any RAT and IMSI.
|
||||
val templateAll = buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL)
|
||||
// Build template with UNKNOWN RAT that matches mobile identities with RAT that
|
||||
// cannot be determined.
|
||||
val templateUnknown =
|
||||
buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UNKNOWN)
|
||||
|
||||
val identUmts = buildNetworkIdentity(
|
||||
mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_UMTS)
|
||||
val identHsdpa = buildNetworkIdentity(
|
||||
mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_HSDPA)
|
||||
val identLte = buildNetworkIdentity(
|
||||
mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_LTE)
|
||||
val identCombined = buildNetworkIdentity(
|
||||
mockContext, stateMobile, false, SUBTYPE_COMBINED)
|
||||
val identImsi2 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI2),
|
||||
false, TelephonyManager.NETWORK_TYPE_UMTS)
|
||||
val identWifi = buildNetworkIdentity(
|
||||
mockContext, buildWifiNetworkState(TEST_SSID1), true, 0)
|
||||
|
||||
// Assert that identity with the same RAT matches.
|
||||
templateUmts.assertMatches(identUmts)
|
||||
templateAll.assertMatches(identUmts)
|
||||
templateUnknown.assertDoesNotMatch(identUmts)
|
||||
// Assert that identity with the RAT within the same group matches.
|
||||
templateUmts.assertMatches(identHsdpa)
|
||||
templateAll.assertMatches(identHsdpa)
|
||||
templateUnknown.assertDoesNotMatch(identHsdpa)
|
||||
// Assert that identity with the RAT out of the same group only matches template with
|
||||
// NETWORK_TYPE_ALL.
|
||||
templateUmts.assertDoesNotMatch(identLte)
|
||||
templateAll.assertMatches(identLte)
|
||||
templateUnknown.assertDoesNotMatch(identLte)
|
||||
// Assert that identity with combined RAT only matches with template with NETWORK_TYPE_ALL
|
||||
// and NETWORK_TYPE_UNKNOWN.
|
||||
templateUmts.assertDoesNotMatch(identCombined)
|
||||
templateAll.assertMatches(identCombined)
|
||||
templateUnknown.assertMatches(identCombined)
|
||||
// Assert that identity with different IMSI matches.
|
||||
templateUmts.assertMatches(identImsi2)
|
||||
templateAll.assertMatches(identImsi2)
|
||||
templateUnknown.assertDoesNotMatch(identImsi2)
|
||||
// Assert that wifi identity does not match.
|
||||
templateUmts.assertDoesNotMatch(identWifi)
|
||||
templateAll.assertDoesNotMatch(identWifi)
|
||||
templateUnknown.assertDoesNotMatch(identWifi)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testParcelUnparcel() {
|
||||
val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, null, null, METERED_ALL,
|
||||
ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_LTE)
|
||||
val templateWifi = NetworkTemplate(MATCH_WIFI, null, null, TEST_SSID1, METERED_ALL,
|
||||
ROAMING_ALL, DEFAULT_NETWORK_ALL, 0)
|
||||
assertParcelSane(templateMobile, 8)
|
||||
assertParcelSane(templateWifi, 8)
|
||||
}
|
||||
|
||||
// Verify NETWORK_TYPE_ALL does not conflict with TelephonyManager#NETWORK_TYPE_* constants.
|
||||
@Test
|
||||
fun testNetworkTypeAll() {
|
||||
for (ratType in TelephonyManager.getAllNetworkTypes()) {
|
||||
assertNotEquals(NETWORK_TYPE_ALL, ratType)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -319,33 +319,33 @@ public class NetworkStatsCollectionTest {
|
||||
assertEntry(18322, 75, 15031, 75, history.getValues(i++, null));
|
||||
assertEntry(527798, 761, 78570, 652, history.getValues(i++, null));
|
||||
assertEntry(527797, 760, 78570, 651, history.getValues(i++, null));
|
||||
assertEntry(10747, 50, 16838, 55, history.getValues(i++, null));
|
||||
assertEntry(10747, 49, 16838, 54, history.getValues(i++, null));
|
||||
assertEntry(10747, 50, 16839, 55, history.getValues(i++, null));
|
||||
assertEntry(10747, 49, 16837, 54, history.getValues(i++, null));
|
||||
assertEntry(89191, 151, 18021, 140, history.getValues(i++, null));
|
||||
assertEntry(89190, 150, 18020, 139, history.getValues(i++, null));
|
||||
assertEntry(3821, 22, 4525, 26, history.getValues(i++, null));
|
||||
assertEntry(3820, 22, 4524, 26, history.getValues(i++, null));
|
||||
assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
|
||||
assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
|
||||
assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
|
||||
assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
|
||||
assertEntry(3821, 23, 4525, 26, history.getValues(i++, null));
|
||||
assertEntry(3820, 21, 4524, 26, history.getValues(i++, null));
|
||||
assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
|
||||
assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
|
||||
assertEntry(8289, 36, 6864, 39, history.getValues(i++, null));
|
||||
assertEntry(8289, 34, 6862, 37, history.getValues(i++, null));
|
||||
assertEntry(113914, 174, 18364, 157, history.getValues(i++, null));
|
||||
assertEntry(113913, 173, 18364, 157, history.getValues(i++, null));
|
||||
assertEntry(11378, 49, 9261, 49, history.getValues(i++, null));
|
||||
assertEntry(11377, 48, 9261, 49, history.getValues(i++, null));
|
||||
assertEntry(201765, 328, 41808, 291, history.getValues(i++, null));
|
||||
assertEntry(201765, 328, 41807, 290, history.getValues(i++, null));
|
||||
assertEntry(106106, 218, 39917, 201, history.getValues(i++, null));
|
||||
assertEntry(106105, 217, 39917, 201, history.getValues(i++, null));
|
||||
assertEntry(11378, 49, 9261, 50, history.getValues(i++, null));
|
||||
assertEntry(11377, 48, 9261, 48, history.getValues(i++, null));
|
||||
assertEntry(201766, 328, 41808, 291, history.getValues(i++, null));
|
||||
assertEntry(201764, 328, 41807, 290, history.getValues(i++, null));
|
||||
assertEntry(106106, 219, 39918, 202, history.getValues(i++, null));
|
||||
assertEntry(106105, 216, 39916, 200, history.getValues(i++, null));
|
||||
assertEquals(history.size(), i);
|
||||
|
||||
// Slice from middle should be untouched
|
||||
history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS,
|
||||
TIME_B + HOUR_IN_MILLIS); i = 0;
|
||||
assertEntry(3821, 22, 4525, 26, history.getValues(i++, null));
|
||||
assertEntry(3820, 22, 4524, 26, history.getValues(i++, null));
|
||||
assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
|
||||
assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
|
||||
assertEntry(3821, 23, 4525, 26, history.getValues(i++, null));
|
||||
assertEntry(3820, 21, 4524, 26, history.getValues(i++, null));
|
||||
assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
|
||||
assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
|
||||
assertEquals(history.size(), i);
|
||||
}
|
||||
|
||||
@@ -373,25 +373,25 @@ public class NetworkStatsCollectionTest {
|
||||
assertEntry(527797, 760, 78570, 651, history.getValues(i++, null));
|
||||
// Cycle point; start data normalization
|
||||
assertEntry(7507, 0, 11763, 0, history.getValues(i++, null));
|
||||
assertEntry(7507, 0, 11763, 0, history.getValues(i++, null));
|
||||
assertEntry(7507, 0, 11762, 0, history.getValues(i++, null));
|
||||
assertEntry(62309, 0, 12589, 0, history.getValues(i++, null));
|
||||
assertEntry(62309, 0, 12588, 0, history.getValues(i++, null));
|
||||
assertEntry(2669, 0, 3161, 0, history.getValues(i++, null));
|
||||
assertEntry(2668, 0, 3160, 0, history.getValues(i++, null));
|
||||
// Anchor point; end data normalization
|
||||
assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
|
||||
assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
|
||||
assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
|
||||
assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
|
||||
assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
|
||||
assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
|
||||
assertEntry(8289, 36, 6864, 39, history.getValues(i++, null));
|
||||
assertEntry(8289, 34, 6862, 37, history.getValues(i++, null));
|
||||
assertEntry(113914, 174, 18364, 157, history.getValues(i++, null));
|
||||
assertEntry(113913, 173, 18364, 157, history.getValues(i++, null));
|
||||
// Cycle point
|
||||
assertEntry(11378, 49, 9261, 49, history.getValues(i++, null));
|
||||
assertEntry(11377, 48, 9261, 49, history.getValues(i++, null));
|
||||
assertEntry(201765, 328, 41808, 291, history.getValues(i++, null));
|
||||
assertEntry(201765, 328, 41807, 290, history.getValues(i++, null));
|
||||
assertEntry(106106, 218, 39917, 201, history.getValues(i++, null));
|
||||
assertEntry(106105, 217, 39917, 201, history.getValues(i++, null));
|
||||
assertEntry(11378, 49, 9261, 50, history.getValues(i++, null));
|
||||
assertEntry(11377, 48, 9261, 48, history.getValues(i++, null));
|
||||
assertEntry(201766, 328, 41808, 291, history.getValues(i++, null));
|
||||
assertEntry(201764, 328, 41807, 290, history.getValues(i++, null));
|
||||
assertEntry(106106, 219, 39918, 202, history.getValues(i++, null));
|
||||
assertEntry(106105, 216, 39916, 200, history.getValues(i++, null));
|
||||
assertEquals(history.size(), i);
|
||||
|
||||
// Slice from middle should be augmented
|
||||
@@ -399,8 +399,8 @@ public class NetworkStatsCollectionTest {
|
||||
TIME_B + HOUR_IN_MILLIS); i = 0;
|
||||
assertEntry(2669, 0, 3161, 0, history.getValues(i++, null));
|
||||
assertEntry(2668, 0, 3160, 0, history.getValues(i++, null));
|
||||
assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
|
||||
assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
|
||||
assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
|
||||
assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
|
||||
assertEquals(history.size(), i);
|
||||
}
|
||||
|
||||
@@ -427,34 +427,34 @@ public class NetworkStatsCollectionTest {
|
||||
assertEntry(527798, 761, 78570, 652, history.getValues(i++, null));
|
||||
assertEntry(527797, 760, 78570, 651, history.getValues(i++, null));
|
||||
// Cycle point; start data normalization
|
||||
assertEntry(15015, 0, 23526, 0, history.getValues(i++, null));
|
||||
assertEntry(15015, 0, 23526, 0, history.getValues(i++, null));
|
||||
assertEntry(15015, 0, 23527, 0, history.getValues(i++, null));
|
||||
assertEntry(15015, 0, 23524, 0, history.getValues(i++, null));
|
||||
assertEntry(124619, 0, 25179, 0, history.getValues(i++, null));
|
||||
assertEntry(124618, 0, 25177, 0, history.getValues(i++, null));
|
||||
assertEntry(5338, 0, 6322, 0, history.getValues(i++, null));
|
||||
assertEntry(5337, 0, 6320, 0, history.getValues(i++, null));
|
||||
// Anchor point; end data normalization
|
||||
assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
|
||||
assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
|
||||
assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
|
||||
assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
|
||||
assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
|
||||
assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
|
||||
assertEntry(8289, 36, 6864, 39, history.getValues(i++, null));
|
||||
assertEntry(8289, 34, 6862, 37, history.getValues(i++, null));
|
||||
assertEntry(113914, 174, 18364, 157, history.getValues(i++, null));
|
||||
assertEntry(113913, 173, 18364, 157, history.getValues(i++, null));
|
||||
// Cycle point
|
||||
assertEntry(11378, 49, 9261, 49, history.getValues(i++, null));
|
||||
assertEntry(11377, 48, 9261, 49, history.getValues(i++, null));
|
||||
assertEntry(201765, 328, 41808, 291, history.getValues(i++, null));
|
||||
assertEntry(201765, 328, 41807, 290, history.getValues(i++, null));
|
||||
assertEntry(106106, 218, 39917, 201, history.getValues(i++, null));
|
||||
assertEntry(106105, 217, 39917, 201, history.getValues(i++, null));
|
||||
assertEntry(11378, 49, 9261, 50, history.getValues(i++, null));
|
||||
assertEntry(11377, 48, 9261, 48, history.getValues(i++, null));
|
||||
assertEntry(201766, 328, 41808, 291, history.getValues(i++, null));
|
||||
assertEntry(201764, 328, 41807, 290, history.getValues(i++, null));
|
||||
assertEntry(106106, 219, 39918, 202, history.getValues(i++, null));
|
||||
assertEntry(106105, 216, 39916, 200, history.getValues(i++, null));
|
||||
|
||||
// Slice from middle should be augmented
|
||||
history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS,
|
||||
TIME_B + HOUR_IN_MILLIS); i = 0;
|
||||
assertEntry(5338, 0, 6322, 0, history.getValues(i++, null));
|
||||
assertEntry(5337, 0, 6320, 0, history.getValues(i++, null));
|
||||
assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
|
||||
assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
|
||||
assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
|
||||
assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
|
||||
assertEquals(history.size(), i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import static android.net.NetworkStats.TAG_NONE;
|
||||
import static android.net.NetworkStats.UID_ALL;
|
||||
import static android.net.NetworkStatsHistory.FIELD_ALL;
|
||||
import static android.net.NetworkTemplate.buildTemplateMobileAll;
|
||||
import static android.net.NetworkTemplate.buildTemplateMobileWithRatType;
|
||||
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
|
||||
import static android.net.TrafficStats.MB_IN_BYTES;
|
||||
import static android.net.TrafficStats.UID_REMOVED;
|
||||
@@ -60,11 +61,13 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.usage.NetworkStatsManager;
|
||||
import android.content.Context;
|
||||
@@ -92,6 +95,8 @@ import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SimpleClock;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
@@ -163,11 +168,14 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
private @Mock NetworkStatsSettings mSettings;
|
||||
private @Mock IBinder mBinder;
|
||||
private @Mock AlarmManager mAlarmManager;
|
||||
private @Mock TelephonyManager mTelephonyManager;
|
||||
private HandlerThread mHandlerThread;
|
||||
|
||||
private NetworkStatsService mService;
|
||||
private INetworkStatsSession mSession;
|
||||
private INetworkManagementEventObserver mNetworkObserver;
|
||||
@Nullable
|
||||
private PhoneStateListener mPhoneStateListener;
|
||||
|
||||
private final Clock mClock = new SimpleClock(ZoneOffset.UTC) {
|
||||
@Override
|
||||
@@ -195,7 +203,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
mHandlerThread = new HandlerThread("HandlerThread");
|
||||
final NetworkStatsService.Dependencies deps = makeDependencies();
|
||||
mService = new NetworkStatsService(mServiceContext, mNetManager, mAlarmManager, wakeLock,
|
||||
mClock, mServiceContext.getSystemService(TelephonyManager.class), mSettings,
|
||||
mClock, mTelephonyManager, mSettings,
|
||||
mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir), deps);
|
||||
|
||||
mElapsedRealtime = 0L;
|
||||
@@ -216,6 +224,12 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
|
||||
verify(mNetManager).registerObserver(networkObserver.capture());
|
||||
mNetworkObserver = networkObserver.getValue();
|
||||
|
||||
// Capture the phone state listener that created by service.
|
||||
final ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor =
|
||||
ArgumentCaptor.forClass(PhoneStateListener.class);
|
||||
verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), anyInt());
|
||||
mPhoneStateListener = phoneStateListenerCaptor.getValue();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -534,7 +548,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUid3g4gCombinedByTemplate() throws Exception {
|
||||
public void testUid3gWimaxCombinedByTemplate() throws Exception {
|
||||
// pretend that network comes online
|
||||
expectDefaultSettings();
|
||||
NetworkState[] states = new NetworkState[] {buildMobile3gState(IMSI_1)};
|
||||
@@ -558,10 +572,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 8L, 1024L, 8L, 5);
|
||||
|
||||
|
||||
// now switch over to 4g network
|
||||
// now switch over to wimax network
|
||||
incrementCurrentTime(HOUR_IN_MILLIS);
|
||||
expectDefaultSettings();
|
||||
states = new NetworkState[] {buildMobile4gState(TEST_IFACE2)};
|
||||
states = new NetworkState[] {buildWimaxState(TEST_IFACE2)};
|
||||
expectNetworkStatsSummary(buildEmptyStats());
|
||||
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
|
||||
.insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
|
||||
@@ -588,6 +602,89 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 1280L, 10L, 10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMobileStatsByRatType() throws Exception {
|
||||
final NetworkTemplate template3g =
|
||||
buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS);
|
||||
final NetworkTemplate template4g =
|
||||
buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_LTE);
|
||||
final NetworkTemplate template5g =
|
||||
buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_NR);
|
||||
final NetworkState[] states = new NetworkState[]{buildMobile3gState(IMSI_1)};
|
||||
|
||||
// 3G network comes online.
|
||||
expectNetworkStatsSummary(buildEmptyStats());
|
||||
expectNetworkStatsUidDetail(buildEmptyStats());
|
||||
|
||||
setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS);
|
||||
mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
|
||||
new VpnInfo[0]);
|
||||
|
||||
// Create some traffic.
|
||||
incrementCurrentTime(MINUTE_IN_MILLIS);
|
||||
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
|
||||
.addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
|
||||
12L, 18L, 14L, 1L, 0L)));
|
||||
forcePollAndWaitForIdle();
|
||||
|
||||
// Verify 3g templates gets stats.
|
||||
assertUidTotal(sTemplateImsi1, UID_RED, 12L, 18L, 14L, 1L, 0);
|
||||
assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0);
|
||||
assertUidTotal(template4g, UID_RED, 0L, 0L, 0L, 0L, 0);
|
||||
assertUidTotal(template5g, UID_RED, 0L, 0L, 0L, 0L, 0);
|
||||
|
||||
// 4G network comes online.
|
||||
incrementCurrentTime(MINUTE_IN_MILLIS);
|
||||
setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_LTE);
|
||||
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
|
||||
// Append more traffic on existing 3g stats entry.
|
||||
.addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
|
||||
16L, 22L, 17L, 2L, 0L))
|
||||
// Add entry that is new on 4g.
|
||||
.addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE,
|
||||
33L, 27L, 8L, 10L, 1L)));
|
||||
forcePollAndWaitForIdle();
|
||||
|
||||
// Verify ALL_MOBILE template gets all. 3g template counters do not increase.
|
||||
assertUidTotal(sTemplateImsi1, UID_RED, 49L, 49L, 25L, 12L, 1);
|
||||
assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0);
|
||||
// Verify 4g template counts appended stats on existing entry and newly created entry.
|
||||
assertUidTotal(template4g, UID_RED, 4L + 33L, 4L + 27L, 3L + 8L, 1L + 10L, 1);
|
||||
// Verify 5g template doesn't get anything since no traffic is generated on 5g.
|
||||
assertUidTotal(template5g, UID_RED, 0L, 0L, 0L, 0L, 0);
|
||||
|
||||
// 5g network comes online.
|
||||
incrementCurrentTime(MINUTE_IN_MILLIS);
|
||||
setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_NR);
|
||||
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
|
||||
// Existing stats remains.
|
||||
.addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
|
||||
16L, 22L, 17L, 2L, 0L))
|
||||
.addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE,
|
||||
33L, 27L, 8L, 10L, 1L))
|
||||
// Add some traffic on 5g.
|
||||
.addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
|
||||
5L, 13L, 31L, 9L, 2L)));
|
||||
forcePollAndWaitForIdle();
|
||||
|
||||
// Verify ALL_MOBILE template gets all.
|
||||
assertUidTotal(sTemplateImsi1, UID_RED, 54L, 62L, 56L, 21L, 3);
|
||||
// 3g/4g template counters do not increase.
|
||||
assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0);
|
||||
assertUidTotal(template4g, UID_RED, 4L + 33L, 4L + 27L, 3L + 8L, 1L + 10L, 1);
|
||||
// Verify 5g template gets the 5g count.
|
||||
assertUidTotal(template5g, UID_RED, 5L, 13L, 31L, 9L, 2);
|
||||
}
|
||||
|
||||
// TODO: support per IMSI state
|
||||
private void setMobileRatTypeAndWaitForIdle(int ratType) {
|
||||
final ServiceState mockSs = mock(ServiceState.class);
|
||||
when(mockSs.getDataNetworkType()).thenReturn(ratType);
|
||||
mPhoneStateListener.onServiceStateChanged(mockSs);
|
||||
|
||||
HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSummaryForAllUid() throws Exception {
|
||||
// pretend that network comes online
|
||||
@@ -1197,6 +1294,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
when(mSettings.getPollInterval()).thenReturn(HOUR_IN_MILLIS);
|
||||
when(mSettings.getPollDelay()).thenReturn(0L);
|
||||
when(mSettings.getSampleEnabled()).thenReturn(true);
|
||||
when(mSettings.getCombineSubtypeEnabled()).thenReturn(false);
|
||||
|
||||
final Config config = new Config(bucketDuration, deleteAge, deleteAge);
|
||||
when(mSettings.getDevConfig()).thenReturn(config);
|
||||
@@ -1242,6 +1340,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
final NetworkCapabilities capabilities = new NetworkCapabilities();
|
||||
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !isMetered);
|
||||
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true);
|
||||
capabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
|
||||
return new NetworkState(info, prop, capabilities, WIFI_NETWORK, null, TEST_SSID);
|
||||
}
|
||||
|
||||
@@ -1259,10 +1358,11 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
final NetworkCapabilities capabilities = new NetworkCapabilities();
|
||||
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false);
|
||||
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming);
|
||||
capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
|
||||
return new NetworkState(info, prop, capabilities, MOBILE_NETWORK, subscriberId, null);
|
||||
}
|
||||
|
||||
private static NetworkState buildMobile4gState(String iface) {
|
||||
private static NetworkState buildWimaxState(@NonNull String iface) {
|
||||
final NetworkInfo info = new NetworkInfo(TYPE_WIMAX, 0, null, null);
|
||||
info.setDetailedState(DetailedState.CONNECTED, null, null);
|
||||
final LinkProperties prop = new LinkProperties();
|
||||
|
||||
Reference in New Issue
Block a user