Merge "[ST01] Attributes data usage of test network by specifier"
This commit is contained in:
@@ -85,6 +85,12 @@ public class NetworkIdentity {
|
||||
|
||||
private static final long SUPPORTED_OEM_MANAGED_TYPES = OEM_PAID | OEM_PRIVATE;
|
||||
|
||||
// Need to be synchronized with ConnectivityManager.
|
||||
// TODO: Use {@code ConnectivityManager#*} when visible.
|
||||
static final int TYPE_TEST = 18;
|
||||
private static final int MAX_NETWORK_TYPE = TYPE_TEST;
|
||||
private static final int MIN_NETWORK_TYPE = TYPE_MOBILE;
|
||||
|
||||
final int mType;
|
||||
final int mRatType;
|
||||
final int mSubId;
|
||||
@@ -346,11 +352,6 @@ public class NetworkIdentity {
|
||||
* Builder class for {@link NetworkIdentity}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
// Need to be synchronized with ConnectivityManager.
|
||||
// TODO: Use {@link ConnectivityManager#MAX_NETWORK_TYPE} when this file is in the module.
|
||||
private static final int MAX_NETWORK_TYPE = 18; // TYPE_TEST
|
||||
private static final int MIN_NETWORK_TYPE = TYPE_MOBILE;
|
||||
|
||||
private int mType;
|
||||
private int mRatType;
|
||||
private String mSubscriberId;
|
||||
@@ -413,6 +414,12 @@ public class NetworkIdentity {
|
||||
final WifiInfo info = (WifiInfo) transportInfo;
|
||||
setWifiNetworkKey(info.getNetworkKey());
|
||||
}
|
||||
} else if (mType == TYPE_TEST) {
|
||||
final NetworkSpecifier ns = snapshot.getNetworkCapabilities().getNetworkSpecifier();
|
||||
if (ns instanceof TestNetworkSpecifier) {
|
||||
// Reuse the wifi network key field to identify individual test networks.
|
||||
setWifiNetworkKey(((TestNetworkSpecifier) ns).getInterfaceName());
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -574,7 +581,7 @@ public class NetworkIdentity {
|
||||
}
|
||||
|
||||
// Assert non-wifi network cannot have a wifi network key.
|
||||
if (mType != TYPE_WIFI && mWifiNetworkKey != null) {
|
||||
if (mType != TYPE_WIFI && mType != TYPE_TEST && mWifiNetworkKey != null) {
|
||||
throw new IllegalArgumentException("Invalid wifi network key for type " + mType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.net.module.util.CollectionUtils;
|
||||
import com.android.net.module.util.NetworkIdentityUtils;
|
||||
import com.android.net.module.util.NetworkStatsUtils;
|
||||
@@ -114,6 +115,14 @@ public final class NetworkTemplate implements Parcelable {
|
||||
* may offer non-cellular networks like WiFi, which will be matched by this rule.
|
||||
*/
|
||||
public static final int MATCH_CARRIER = 10;
|
||||
/**
|
||||
* Match rule to match networks with {@link ConnectivityManager#TYPE_TEST} as the legacy
|
||||
* network type.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static final int MATCH_TEST = 11;
|
||||
|
||||
// TODO: Remove this and replace all callers with WIFI_NETWORK_KEY_ALL.
|
||||
/** @hide */
|
||||
@@ -176,6 +185,7 @@ public final class NetworkTemplate implements Parcelable {
|
||||
case MATCH_BLUETOOTH:
|
||||
case MATCH_PROXY:
|
||||
case MATCH_CARRIER:
|
||||
case MATCH_TEST:
|
||||
return true;
|
||||
|
||||
default:
|
||||
@@ -666,6 +676,8 @@ public final class NetworkTemplate implements Parcelable {
|
||||
return matchesProxy(ident);
|
||||
case MATCH_CARRIER:
|
||||
return matchesCarrier(ident);
|
||||
case MATCH_TEST:
|
||||
return matchesTest(ident);
|
||||
default:
|
||||
// We have no idea what kind of network template we are, so we
|
||||
// just claim not to match anything.
|
||||
@@ -776,6 +788,17 @@ public final class NetworkTemplate implements Parcelable {
|
||||
&& CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if matches test network. If the wifiNetworkKeys in the template is specified, Then it
|
||||
* will only match a network containing any of the specified the wifi network key. Otherwise,
|
||||
* all test networks would be matched.
|
||||
*/
|
||||
private boolean matchesTest(NetworkIdentity ident) {
|
||||
return ident.mType == NetworkIdentity.TYPE_TEST
|
||||
&& ((CollectionUtils.isEmpty(mMatchWifiNetworkKeys)
|
||||
|| CollectionUtils.contains(mMatchWifiNetworkKeys, ident.mWifiNetworkKey)));
|
||||
}
|
||||
|
||||
private boolean matchesMobileWildcard(NetworkIdentity ident) {
|
||||
if (ident.mType == TYPE_WIMAX) {
|
||||
return true;
|
||||
@@ -829,6 +852,8 @@ public final class NetworkTemplate implements Parcelable {
|
||||
return "PROXY";
|
||||
case MATCH_CARRIER:
|
||||
return "CARRIER";
|
||||
case MATCH_TEST:
|
||||
return "TEST";
|
||||
default:
|
||||
return "UNKNOWN(" + matchRule + ")";
|
||||
}
|
||||
@@ -1079,7 +1104,9 @@ public final class NetworkTemplate implements Parcelable {
|
||||
}
|
||||
|
||||
private void validateWifiNetworkKeys() {
|
||||
if (mMatchRule != MATCH_WIFI && !mMatchWifiNetworkKeys.isEmpty()) {
|
||||
// Also allow querying test networks which use wifi network key as identifier.
|
||||
if (mMatchRule != MATCH_WIFI && mMatchRule != MATCH_TEST
|
||||
&& !mMatchWifiNetworkKeys.isEmpty()) {
|
||||
throw new IllegalArgumentException("Trying to build non wifi match rule: "
|
||||
+ mMatchRule + " with wifi network keys");
|
||||
}
|
||||
|
||||
@@ -1167,6 +1167,8 @@ public class ConnectivityManager {
|
||||
return "PROXY";
|
||||
case TYPE_VPN:
|
||||
return "VPN";
|
||||
case TYPE_TEST:
|
||||
return "TEST";
|
||||
default:
|
||||
return Integer.toString(type);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,10 @@ package android.net
|
||||
import android.app.usage.NetworkStatsManager.NETWORK_TYPE_5G_NSA
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager.TYPE_MOBILE
|
||||
import android.net.ConnectivityManager.TYPE_TEST
|
||||
import android.net.ConnectivityManager.TYPE_WIFI
|
||||
import android.net.NetworkCapabilities.TRANSPORT_TEST
|
||||
import android.net.NetworkCapabilities.TRANSPORT_WIFI
|
||||
import android.net.NetworkIdentity.OEM_NONE
|
||||
import android.net.NetworkIdentity.OEM_PAID
|
||||
import android.net.NetworkIdentity.OEM_PRIVATE
|
||||
@@ -31,6 +34,7 @@ import android.net.NetworkStats.METERED_YES
|
||||
import android.net.NetworkStats.ROAMING_ALL
|
||||
import android.net.NetworkTemplate.MATCH_MOBILE
|
||||
import android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD
|
||||
import android.net.NetworkTemplate.MATCH_TEST
|
||||
import android.net.NetworkTemplate.MATCH_WIFI
|
||||
import android.net.NetworkTemplate.MATCH_WIFI_WILDCARD
|
||||
import android.net.NetworkTemplate.NETWORK_TYPE_ALL
|
||||
@@ -97,6 +101,14 @@ class NetworkTemplateTest {
|
||||
(oemManaged and OEM_PAID) == OEM_PAID)
|
||||
setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE,
|
||||
(oemManaged and OEM_PRIVATE) == OEM_PRIVATE)
|
||||
if (type == TYPE_TEST) {
|
||||
wifiKey?.let { TestNetworkSpecifier(it) }?.let {
|
||||
// Must have a single non-test transport specified to use setNetworkSpecifier.
|
||||
// Put an arbitrary transport type which is not used in this test.
|
||||
addTransportType(TRANSPORT_TEST)
|
||||
addTransportType(TRANSPORT_WIFI)
|
||||
setNetworkSpecifier(it) }
|
||||
}
|
||||
setTransportInfo(mockWifiInfo)
|
||||
}
|
||||
return NetworkStateSnapshot(mock(Network::class.java), caps, lp, subscriberId, type)
|
||||
@@ -232,6 +244,32 @@ class NetworkTemplateTest {
|
||||
templateMobileNullImsiWithRatType.assertDoesNotMatch(identWifiImsi1Key1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTestNetworkTemplateMatches() {
|
||||
val templateTestKey1 = NetworkTemplate.Builder(MATCH_TEST)
|
||||
.setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build()
|
||||
val templateTestKey2 = NetworkTemplate.Builder(MATCH_TEST)
|
||||
.setWifiNetworkKeys(setOf(TEST_WIFI_KEY2)).build()
|
||||
val templateTestAll = NetworkTemplate.Builder(MATCH_TEST).build()
|
||||
|
||||
val stateWifiKey1 = buildNetworkState(TYPE_WIFI, null /* subscriberId */, TEST_WIFI_KEY1,
|
||||
OEM_NONE, true /* metered */)
|
||||
val stateTestKey1 = buildNetworkState(TYPE_TEST, null /* subscriberId */, TEST_WIFI_KEY1,
|
||||
OEM_NONE, true /* metered */)
|
||||
val identWifi1 = buildNetworkIdentity(mockContext, stateWifiKey1,
|
||||
false /* defaultNetwork */, NetworkTemplate.NETWORK_TYPE_ALL)
|
||||
val identTest1 = buildNetworkIdentity(mockContext, stateTestKey1,
|
||||
false /* defaultNetwork */, NETWORK_TYPE_ALL)
|
||||
|
||||
// Verify that the template matches corresponding type and the subscriberId.
|
||||
templateTestKey1.assertDoesNotMatch(identWifi1)
|
||||
templateTestKey1.assertMatches(identTest1)
|
||||
templateTestKey2.assertDoesNotMatch(identWifi1)
|
||||
templateTestKey2.assertDoesNotMatch(identTest1)
|
||||
templateTestAll.assertDoesNotMatch(identWifi1)
|
||||
templateTestAll.assertMatches(identTest1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCarrierMeteredMatches() {
|
||||
val templateCarrierImsi1Metered = buildTemplateCarrierMetered(TEST_IMSI1)
|
||||
|
||||
@@ -25,6 +25,7 @@ import static android.content.Intent.EXTRA_UID;
|
||||
import static android.content.pm.PackageManager.PERMISSION_DENIED;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE;
|
||||
import static android.net.ConnectivityManager.TYPE_TEST;
|
||||
import static android.net.ConnectivityManager.TYPE_WIFI;
|
||||
import static android.net.NetworkIdentity.OEM_PAID;
|
||||
import static android.net.NetworkIdentity.OEM_PRIVATE;
|
||||
@@ -48,6 +49,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.MATCH_MOBILE;
|
||||
import static android.net.NetworkTemplate.MATCH_TEST;
|
||||
import static android.net.NetworkTemplate.MATCH_WIFI;
|
||||
import static android.net.NetworkTemplate.OEM_MANAGED_NO;
|
||||
import static android.net.NetworkTemplate.OEM_MANAGED_YES;
|
||||
@@ -107,6 +109,7 @@ import android.net.NetworkStatsCollection;
|
||||
import android.net.NetworkStatsHistory;
|
||||
import android.net.NetworkTemplate;
|
||||
import android.net.TelephonyNetworkSpecifier;
|
||||
import android.net.TestNetworkSpecifier;
|
||||
import android.net.TetherStatsParcel;
|
||||
import android.net.TetheringManager;
|
||||
import android.net.UnderlyingNetworkInfo;
|
||||
@@ -121,6 +124,7 @@ import android.os.SimpleClock;
|
||||
import android.provider.Settings;
|
||||
import android.system.ErrnoException;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Pair;
|
||||
|
||||
@@ -209,9 +213,11 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
private static final Network WIFI_NETWORK = new Network(100);
|
||||
private static final Network MOBILE_NETWORK = new Network(101);
|
||||
private static final Network VPN_NETWORK = new Network(102);
|
||||
private static final Network TEST_NETWORK = new Network(103);
|
||||
|
||||
private static final Network[] NETWORKS_WIFI = new Network[]{ WIFI_NETWORK };
|
||||
private static final Network[] NETWORKS_MOBILE = new Network[]{ MOBILE_NETWORK };
|
||||
private static final Network[] NETWORKS_TEST = new Network[]{ TEST_NETWORK };
|
||||
|
||||
private static final long WAIT_TIMEOUT = 2 * 1000; // 2 secs
|
||||
private static final int INVALID_TYPE = -1;
|
||||
@@ -817,7 +823,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 258L, 512L, 32L, 0);
|
||||
assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 0);
|
||||
|
||||
|
||||
// now pretend two UIDs are uninstalled, which should migrate stats to
|
||||
// special "removed" bucket.
|
||||
mockDefaultSettings();
|
||||
@@ -940,8 +945,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
|
||||
// Pretend that 5g mobile network comes online
|
||||
final NetworkStateSnapshot[] mobileStates =
|
||||
new NetworkStateSnapshot[] {buildMobileState(IMSI_1), buildMobileState(TEST_IFACE2,
|
||||
IMSI_1, true /* isTemporarilyNotMetered */, false /* isRoaming */)};
|
||||
new NetworkStateSnapshot[] {buildMobileState(IMSI_1), buildStateOfTransport(
|
||||
NetworkCapabilities.TRANSPORT_CELLULAR, TYPE_MOBILE,
|
||||
TEST_IFACE2, IMSI_1, null /* wifiNetworkKey */,
|
||||
true /* isTemporarilyNotMetered */, false /* isRoaming */)};
|
||||
setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_NR);
|
||||
mService.notifyNetworkStatus(NETWORKS_MOBILE, mobileStates,
|
||||
getActiveIface(mobileStates), new UnderlyingNetworkInfo[0]);
|
||||
@@ -1172,6 +1179,41 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
// already documented publicly, refer to {@link NetworkStatsManager#queryDetails}.
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryTestNetworkUsage() throws Exception {
|
||||
final NetworkTemplate templateTestAll = new NetworkTemplate.Builder(MATCH_TEST).build();
|
||||
final NetworkTemplate templateTestIface1 = new NetworkTemplate.Builder(MATCH_TEST)
|
||||
.setWifiNetworkKeys(Set.of(TEST_IFACE)).build();
|
||||
final NetworkTemplate templateTestIface2 = new NetworkTemplate.Builder(MATCH_TEST)
|
||||
.setWifiNetworkKeys(Set.of(TEST_IFACE2)).build();
|
||||
// Test networks might use interface as subscriberId to identify individual networks.
|
||||
// Simulate both cases.
|
||||
final NetworkStateSnapshot[] states =
|
||||
new NetworkStateSnapshot[]{buildTestState(TEST_IFACE, TEST_IFACE),
|
||||
buildTestState(TEST_IFACE2, null /* wifiNetworkKey */)};
|
||||
|
||||
// Test networks comes online.
|
||||
mockNetworkStatsSummary(buildEmptyStats());
|
||||
mockNetworkStatsUidDetail(buildEmptyStats());
|
||||
mService.notifyNetworkStatus(NETWORKS_TEST, states, getActiveIface(states),
|
||||
new UnderlyingNetworkInfo[0]);
|
||||
|
||||
// Create some traffic on both interfaces.
|
||||
incrementCurrentTime(MINUTE_IN_MILLIS);
|
||||
mockNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
|
||||
.addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
|
||||
METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 12L, 18L, 14L, 1L, 0L))
|
||||
.addEntry(new NetworkStats.Entry(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE,
|
||||
METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 7L, 3L, 5L, 1L, 1L)));
|
||||
forcePollAndWaitForIdle();
|
||||
|
||||
// Verify test network templates gets stats. Stats of test networks without subscriberId
|
||||
// can only be matched by templates without subscriberId requirement.
|
||||
assertUidTotal(templateTestAll, UID_RED, 19L, 21L, 19L, 2L, 1);
|
||||
assertUidTotal(templateTestIface1, UID_RED, 12L, 18L, 14L, 1L, 0);
|
||||
assertUidTotal(templateTestIface2, UID_RED, 0L, 0L, 0L, 0L, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUidStatsForTransport() throws Exception {
|
||||
// pretend that network comes online
|
||||
@@ -1319,8 +1361,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
// pretend that network comes online
|
||||
mockDefaultSettings();
|
||||
NetworkStateSnapshot[] states =
|
||||
new NetworkStateSnapshot[] {buildMobileState(TEST_IFACE, IMSI_1,
|
||||
false /* isTemporarilyNotMetered */, true /* isRoaming */)};
|
||||
new NetworkStateSnapshot[] {buildStateOfTransport(
|
||||
NetworkCapabilities.TRANSPORT_CELLULAR, TYPE_MOBILE,
|
||||
TEST_IFACE, IMSI_1, null /* wifiNetworkKey */,
|
||||
false /* isTemporarilyNotMetered */, true /* isRoaming */)};
|
||||
mockNetworkStatsSummary(buildEmptyStats());
|
||||
mockNetworkStatsUidDetail(buildEmptyStats());
|
||||
|
||||
@@ -2189,24 +2233,34 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
}
|
||||
|
||||
private static NetworkStateSnapshot buildMobileState(String subscriberId) {
|
||||
return buildMobileState(TEST_IFACE, subscriberId, false /* isTemporarilyNotMetered */,
|
||||
false /* isRoaming */);
|
||||
return buildStateOfTransport(NetworkCapabilities.TRANSPORT_CELLULAR, TYPE_MOBILE,
|
||||
TEST_IFACE, subscriberId, null /* wifiNetworkKey */,
|
||||
false /* isTemporarilyNotMetered */, false /* isRoaming */);
|
||||
}
|
||||
|
||||
private static NetworkStateSnapshot buildMobileState(String iface, String subscriberId,
|
||||
private static NetworkStateSnapshot buildTestState(@NonNull String iface,
|
||||
@Nullable String wifiNetworkKey) {
|
||||
return buildStateOfTransport(NetworkCapabilities.TRANSPORT_TEST, TYPE_TEST,
|
||||
iface, null /* subscriberId */, wifiNetworkKey,
|
||||
false /* isTemporarilyNotMetered */, false /* isRoaming */);
|
||||
}
|
||||
|
||||
private static NetworkStateSnapshot buildStateOfTransport(int transport, int legacyType,
|
||||
String iface, String subscriberId, String wifiNetworkKey,
|
||||
boolean isTemporarilyNotMetered, boolean isRoaming) {
|
||||
final LinkProperties prop = new LinkProperties();
|
||||
prop.setInterfaceName(iface);
|
||||
final NetworkCapabilities capabilities = new NetworkCapabilities();
|
||||
|
||||
if (isTemporarilyNotMetered) {
|
||||
capabilities.addCapability(
|
||||
NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED);
|
||||
}
|
||||
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED,
|
||||
isTemporarilyNotMetered);
|
||||
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming);
|
||||
capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
|
||||
capabilities.addTransportType(transport);
|
||||
if (legacyType == TYPE_TEST && !TextUtils.isEmpty(wifiNetworkKey)) {
|
||||
capabilities.setNetworkSpecifier(new TestNetworkSpecifier(wifiNetworkKey));
|
||||
}
|
||||
return new NetworkStateSnapshot(
|
||||
MOBILE_NETWORK, capabilities, prop, subscriberId, TYPE_MOBILE);
|
||||
MOBILE_NETWORK, capabilities, prop, subscriberId, legacyType);
|
||||
}
|
||||
|
||||
private NetworkStats buildEmptyStats() {
|
||||
|
||||
Reference in New Issue
Block a user