Merge "Remove usage of networkAttributes" am: 5ccc21eb9b am: 5498465192 am: 9df643d6b6

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1623260

Change-Id: I84aa41ee98535b3b258e52cb67b8f7964d63851b
This commit is contained in:
Remi NGUYEN VAN
2021-03-17 22:18:55 +00:00
committed by Automerger Merge Worker
5 changed files with 218 additions and 105 deletions

View File

@@ -42,4 +42,14 @@
-->
</string-array>
<string-array translatable="false" name="config_legacy_networktype_restore_timers">
<item>2,60000</item><!-- mobile_mms -->
<item>3,60000</item><!-- mobile_supl -->
<item>4,60000</item><!-- mobile_dun -->
<item>5,60000</item><!-- mobile_hipri -->
<item>10,60000</item><!-- mobile_fota -->
<item>11,60000</item><!-- mobile_ims -->
<item>12,60000</item><!-- mobile_cbs -->
</string-array>
</resources>

View File

@@ -17,11 +17,11 @@
<overlayable name="ServiceConnectivityResourcesConfig">
<policy type="product|system|vendor">
<!-- Configuration values for ConnectivityService -->
<item type="array" name="config_legacy_networktype_restore_timers"/>
<item type="string" name="config_networkCaptivePortalServerUrl"/>
<item type="integer" name="config_networkTransitionTimeout"/>
<item type="array" name="config_wakeonlan_supported_interfaces"/>
</policy>
</overlayable>
</resources>

View File

@@ -17,6 +17,10 @@
package com.android.server;
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.FEATURE_WIFI;
import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK;
@@ -28,9 +32,23 @@ import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP
import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_PACKET_FAIL_RATE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_CBS;
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_EMERGENCY;
import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
import static android.net.ConnectivityManager.TYPE_MOBILE_IA;
import static android.net.ConnectivityManager.TYPE_MOBILE_IMS;
import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.ConnectivityManager.TYPE_PROXY;
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
@@ -112,7 +130,6 @@ import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkConfig;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMonitorManager;
@@ -626,11 +643,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
private UserManager mUserManager;
private NetworkConfig[] mNetConfigs;
private int mNetworksDefined;
// the set of network types that can only be enabled by system/sig apps
private List mProtectedNetworks;
private List<Integer> mProtectedNetworks;
private Set<String> mWolSupportedInterfaces;
@@ -720,18 +734,63 @@ public class ConnectivityService extends IConnectivityManager.Stub
* They are therefore not thread-safe with respect to each other.
* - getNetworkForType() can be called at any time on binder threads. It is synchronized
* on mTypeLists to be thread-safe with respect to a concurrent remove call.
* - getRestoreTimerForType(type) is also synchronized on mTypeLists.
* - dump is thread-safe with respect to concurrent add and remove calls.
*/
private final ArrayList<NetworkAgentInfo> mTypeLists[];
@NonNull
private final ConnectivityService mService;
// Restore timers for requestNetworkForFeature (network type -> timer in ms). Types without
// an entry have no timer (equivalent to -1). Lazily loaded.
@NonNull
private ArrayMap<Integer, Integer> mRestoreTimers = new ArrayMap<>();
LegacyTypeTracker(@NonNull ConnectivityService service) {
mService = service;
mTypeLists = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
}
public void addSupportedType(int type) {
public void loadSupportedTypes(@NonNull Context ctx, @NonNull TelephonyManager tm) {
final PackageManager pm = ctx.getPackageManager();
if (pm.hasSystemFeature(FEATURE_WIFI)) {
addSupportedType(TYPE_WIFI);
}
if (pm.hasSystemFeature(FEATURE_WIFI_DIRECT)) {
addSupportedType(TYPE_WIFI_P2P);
}
if (tm.isDataCapable()) {
// Telephony does not have granular support for these types: they are either all
// supported, or none is supported
addSupportedType(TYPE_MOBILE);
addSupportedType(TYPE_MOBILE_MMS);
addSupportedType(TYPE_MOBILE_SUPL);
addSupportedType(TYPE_MOBILE_DUN);
addSupportedType(TYPE_MOBILE_HIPRI);
addSupportedType(TYPE_MOBILE_FOTA);
addSupportedType(TYPE_MOBILE_IMS);
addSupportedType(TYPE_MOBILE_CBS);
addSupportedType(TYPE_MOBILE_IA);
addSupportedType(TYPE_MOBILE_EMERGENCY);
}
if (pm.hasSystemFeature(FEATURE_BLUETOOTH)) {
addSupportedType(TYPE_BLUETOOTH);
}
if (pm.hasSystemFeature(FEATURE_WATCH)) {
// TYPE_PROXY is only used on Wear
addSupportedType(TYPE_PROXY);
}
// Ethernet is often not specified in the configs, although many devices can use it via
// USB host adapters. Add it as long as the ethernet service is here.
if (ctx.getSystemService(Context.ETHERNET_SERVICE) != null) {
addSupportedType(TYPE_ETHERNET);
}
// Always add TYPE_VPN as a supported type
addSupportedType(TYPE_VPN);
}
private void addSupportedType(int type) {
if (mTypeLists[type] != null) {
throw new IllegalStateException(
"legacy list for type " + type + "already initialized");
@@ -752,6 +811,35 @@ public class ConnectivityService extends IConnectivityManager.Stub
return null;
}
public int getRestoreTimerForType(int type) {
synchronized (mTypeLists) {
if (mRestoreTimers == null) {
mRestoreTimers = loadRestoreTimers();
}
return mRestoreTimers.getOrDefault(type, -1);
}
}
private ArrayMap<Integer, Integer> loadRestoreTimers() {
final String[] configs = mService.mResources.get().getStringArray(
com.android.connectivity.resources.R.array
.config_legacy_networktype_restore_timers);
final ArrayMap<Integer, Integer> ret = new ArrayMap<>(configs.length);
for (final String config : configs) {
final String[] splits = TextUtils.split(config, ",");
if (splits.length != 2) {
logwtf("Invalid restore timer token count: " + config);
continue;
}
try {
ret.put(Integer.parseInt(splits[0]), Integer.parseInt(splits[1]));
} catch (NumberFormatException e) {
logwtf("Invalid restore timer number format: " + config, e);
}
}
return ret;
}
private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type,
boolean isDefaultNetwork) {
if (DBG) {
@@ -1174,64 +1262,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
// TODO: What is the "correct" way to do determine if this is a wifi only device?
boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false);
log("wifiOnly=" + wifiOnly);
String[] naStrings = context.getResources().getStringArray(
com.android.internal.R.array.networkAttributes);
for (String naString : naStrings) {
try {
NetworkConfig n = new NetworkConfig(naString);
if (VDBG) log("naString=" + naString + " config=" + n);
if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
loge("Error in networkAttributes - ignoring attempt to define type " +
n.type);
continue;
}
if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) {
log("networkAttributes - ignoring mobile as this dev is wifiOnly " +
n.type);
continue;
}
if (mNetConfigs[n.type] != null) {
loge("Error in networkAttributes - ignoring attempt to redefine type " +
n.type);
continue;
}
mLegacyTypeTracker.addSupportedType(n.type);
mNetConfigs[n.type] = n;
mNetworksDefined++;
} catch(Exception e) {
// ignore it - leave the entry null
}
}
// Forcibly add TYPE_VPN as a supported type, if it has not already been added via config.
if (mNetConfigs[TYPE_VPN] == null) {
// mNetConfigs is used only for "restore time", which isn't applicable to VPNs, so we
// don't need to add TYPE_VPN to mNetConfigs.
mLegacyTypeTracker.addSupportedType(TYPE_VPN);
mNetworksDefined++; // used only in the log() statement below.
}
// Do the same for Ethernet, since it's often not specified in the configs, although many
// devices can use it via USB host adapters.
if (mNetConfigs[TYPE_ETHERNET] == null
&& mContext.getSystemService(Context.ETHERNET_SERVICE) != null) {
mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET);
mNetworksDefined++;
}
if (VDBG) log("mNetworksDefined=" + mNetworksDefined);
mProtectedNetworks = new ArrayList<Integer>();
mLegacyTypeTracker.loadSupportedTypes(mContext, mTelephonyManager);
mProtectedNetworks = new ArrayList<>();
int[] protectedNetworks = context.getResources().getIntArray(
com.android.internal.R.array.config_protectedNetworks);
for (int p : protectedNetworks) {
if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
if (mLegacyTypeTracker.isTypeSupported(p) && !mProtectedNetworks.contains(p)) {
mProtectedNetworks.add(p);
} else {
if (DBG) loge("Ignoring protectedNetwork " + p);
@@ -2640,9 +2676,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
// if the system property isn't set, use the value for the apn type
int ret = RESTORE_DEFAULT_NETWORK_DELAY;
if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
(mNetConfigs[networkType] != null)) {
ret = mNetConfigs[networkType].restoreTime;
if (mLegacyTypeTracker.isTypeSupported(networkType)) {
ret = mLegacyTypeTracker.getRestoreTimerForType(networkType);
}
return ret;
}
@@ -4855,6 +4890,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
Log.wtf(TAG, s);
}
private static void logwtf(String s, Throwable t) {
Log.wtf(TAG, s, t);
}
private static void loge(String s) {
Log.e(TAG, s);
}
@@ -8917,13 +8956,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
private int transportTypeToLegacyType(int type) {
switch (type) {
case NetworkCapabilities.TRANSPORT_CELLULAR:
return ConnectivityManager.TYPE_MOBILE;
return TYPE_MOBILE;
case NetworkCapabilities.TRANSPORT_WIFI:
return ConnectivityManager.TYPE_WIFI;
return TYPE_WIFI;
case NetworkCapabilities.TRANSPORT_BLUETOOTH:
return ConnectivityManager.TYPE_BLUETOOTH;
return TYPE_BLUETOOTH;
case NetworkCapabilities.TRANSPORT_ETHERNET:
return ConnectivityManager.TYPE_ETHERNET;
return TYPE_ETHERNET;
default:
loge("Unexpected transport in transportTypeToLegacyType: " + type);
}

View File

@@ -23,6 +23,8 @@ import static android.content.Intent.ACTION_USER_ADDED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.Intent.ACTION_USER_UNLOCKED;
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
import static android.content.pm.PackageManager.FEATURE_WIFI;
import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
@@ -42,6 +44,7 @@ import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
import static android.net.ConnectivityManager.TYPE_PROXY;
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
@@ -1505,6 +1508,9 @@ public class ConnectivityServiceTest {
Looper.prepare();
}
mockDefaultPackages();
mockHasSystemFeature(FEATURE_WIFI, true);
mockHasSystemFeature(FEATURE_WIFI_DIRECT, true);
doReturn(true).when(mTelephonyManager).isDataCapable();
FakeSettingsProvider.clearSettingsProvider();
mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
@@ -1829,7 +1835,8 @@ public class ConnectivityServiceTest {
assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
assertFalse(mCm.isNetworkSupported(TYPE_PROXY));
// Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
// mocks, this assert exercises the ConnectivityService code path that ensures that

View File

@@ -21,13 +21,29 @@
package com.android.server
import android.content.Context
import android.content.pm.PackageManager
import android.content.pm.PackageManager.FEATURE_WIFI
import android.content.pm.PackageManager.FEATURE_WIFI_DIRECT
import android.net.ConnectivityManager.TYPE_ETHERNET
import android.net.ConnectivityManager.TYPE_MOBILE
import android.net.ConnectivityManager.TYPE_MOBILE_CBS
import android.net.ConnectivityManager.TYPE_MOBILE_DUN
import android.net.ConnectivityManager.TYPE_MOBILE_EMERGENCY
import android.net.ConnectivityManager.TYPE_MOBILE_FOTA
import android.net.ConnectivityManager.TYPE_MOBILE_HIPRI
import android.net.ConnectivityManager.TYPE_MOBILE_IA
import android.net.ConnectivityManager.TYPE_MOBILE_IMS
import android.net.ConnectivityManager.TYPE_MOBILE_MMS
import android.net.ConnectivityManager.TYPE_MOBILE_SUPL
import android.net.ConnectivityManager.TYPE_VPN
import android.net.ConnectivityManager.TYPE_WIFI
import android.net.ConnectivityManager.TYPE_WIFI_P2P
import android.net.ConnectivityManager.TYPE_WIMAX
import android.net.EthernetManager
import android.net.NetworkInfo.DetailedState.CONNECTED
import android.net.NetworkInfo.DetailedState.DISCONNECTED
import android.telephony.TelephonyManager
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.server.ConnectivityService.LegacyTypeTracker
@@ -36,7 +52,6 @@ import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertSame
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
@@ -52,88 +67,130 @@ const val UNSUPPORTED_TYPE = TYPE_WIMAX
@RunWith(AndroidJUnit4::class)
@SmallTest
class LegacyTypeTrackerTest {
private val supportedTypes = arrayOf(TYPE_MOBILE, TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_SUPL)
private val supportedTypes = arrayOf(TYPE_WIFI, TYPE_WIFI_P2P, TYPE_ETHERNET, TYPE_MOBILE,
TYPE_MOBILE_SUPL, TYPE_MOBILE_MMS, TYPE_MOBILE_SUPL, TYPE_MOBILE_DUN, TYPE_MOBILE_HIPRI,
TYPE_MOBILE_FOTA, TYPE_MOBILE_IMS, TYPE_MOBILE_CBS, TYPE_MOBILE_IA,
TYPE_MOBILE_EMERGENCY, TYPE_VPN)
private val mMockService = mock(ConnectivityService::class.java).apply {
doReturn(false).`when`(this).isDefaultNetwork(any())
}
private val mTracker = LegacyTypeTracker(mMockService).apply {
supportedTypes.forEach {
addSupportedType(it)
}
private val mPm = mock(PackageManager::class.java)
private val mContext = mock(Context::class.java).apply {
doReturn(true).`when`(mPm).hasSystemFeature(FEATURE_WIFI)
doReturn(true).`when`(mPm).hasSystemFeature(FEATURE_WIFI_DIRECT)
doReturn(mPm).`when`(this).packageManager
doReturn(mock(EthernetManager::class.java)).`when`(this).getSystemService(
Context.ETHERNET_SERVICE)
}
private val mTm = mock(TelephonyManager::class.java).apply {
doReturn(true).`when`(this).isDataCapable
}
private fun makeTracker() = LegacyTypeTracker(mMockService).apply {
loadSupportedTypes(mContext, mTm)
}
@Test
fun testSupportedTypes() {
try {
mTracker.addSupportedType(supportedTypes[0])
fail("Expected IllegalStateException")
} catch (expected: IllegalStateException) {}
val tracker = makeTracker()
supportedTypes.forEach {
assertTrue(mTracker.isTypeSupported(it))
assertTrue(tracker.isTypeSupported(it))
}
assertFalse(tracker.isTypeSupported(UNSUPPORTED_TYPE))
}
@Test
fun testSupportedTypes_NoEthernet() {
doReturn(null).`when`(mContext).getSystemService(Context.ETHERNET_SERVICE)
assertFalse(makeTracker().isTypeSupported(TYPE_ETHERNET))
}
@Test
fun testSupportedTypes_NoTelephony() {
doReturn(false).`when`(mTm).isDataCapable
val tracker = makeTracker()
val nonMobileTypes = arrayOf(TYPE_WIFI, TYPE_WIFI_P2P, TYPE_ETHERNET, TYPE_VPN)
nonMobileTypes.forEach {
assertTrue(tracker.isTypeSupported(it))
}
supportedTypes.toSet().minus(nonMobileTypes).forEach {
assertFalse(tracker.isTypeSupported(it))
}
}
@Test
fun testSupportedTypes_NoWifiDirect() {
doReturn(false).`when`(mPm).hasSystemFeature(FEATURE_WIFI_DIRECT)
val tracker = makeTracker()
assertFalse(tracker.isTypeSupported(TYPE_WIFI_P2P))
supportedTypes.toSet().minus(TYPE_WIFI_P2P).forEach {
assertTrue(tracker.isTypeSupported(it))
}
assertFalse(mTracker.isTypeSupported(UNSUPPORTED_TYPE))
}
@Test
fun testSupl() {
val tracker = makeTracker()
val mobileNai = mock(NetworkAgentInfo::class.java)
mTracker.add(TYPE_MOBILE, mobileNai)
tracker.add(TYPE_MOBILE, mobileNai)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE)
reset(mMockService)
mTracker.add(TYPE_MOBILE_SUPL, mobileNai)
tracker.add(TYPE_MOBILE_SUPL, mobileNai)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL)
reset(mMockService)
mTracker.remove(TYPE_MOBILE_SUPL, mobileNai, false /* wasDefault */)
tracker.remove(TYPE_MOBILE_SUPL, mobileNai, false /* wasDefault */)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL)
reset(mMockService)
mTracker.add(TYPE_MOBILE_SUPL, mobileNai)
tracker.add(TYPE_MOBILE_SUPL, mobileNai)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL)
reset(mMockService)
mTracker.remove(mobileNai, false)
tracker.remove(mobileNai, false)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE)
}
@Test
fun testAddNetwork() {
val tracker = makeTracker()
val mobileNai = mock(NetworkAgentInfo::class.java)
val wifiNai = mock(NetworkAgentInfo::class.java)
mTracker.add(TYPE_MOBILE, mobileNai)
mTracker.add(TYPE_WIFI, wifiNai)
assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai)
assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai)
tracker.add(TYPE_MOBILE, mobileNai)
tracker.add(TYPE_WIFI, wifiNai)
assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai)
assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai)
// Make sure adding a second NAI does not change the results.
val secondMobileNai = mock(NetworkAgentInfo::class.java)
mTracker.add(TYPE_MOBILE, secondMobileNai)
assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai)
assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai)
tracker.add(TYPE_MOBILE, secondMobileNai)
assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai)
assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai)
// Make sure removing a network that wasn't added for this type is a no-op.
mTracker.remove(TYPE_MOBILE, wifiNai, false /* wasDefault */)
assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai)
assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai)
tracker.remove(TYPE_MOBILE, wifiNai, false /* wasDefault */)
assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai)
assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai)
// Remove the top network for mobile and make sure the second one becomes the network
// of record for this type.
mTracker.remove(TYPE_MOBILE, mobileNai, false /* wasDefault */)
assertSame(mTracker.getNetworkForType(TYPE_MOBILE), secondMobileNai)
assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai)
tracker.remove(TYPE_MOBILE, mobileNai, false /* wasDefault */)
assertSame(tracker.getNetworkForType(TYPE_MOBILE), secondMobileNai)
assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai)
// Make sure adding a network for an unsupported type does not register it.
mTracker.add(UNSUPPORTED_TYPE, mobileNai)
assertNull(mTracker.getNetworkForType(UNSUPPORTED_TYPE))
tracker.add(UNSUPPORTED_TYPE, mobileNai)
assertNull(tracker.getNetworkForType(UNSUPPORTED_TYPE))
}
@Test
fun testBroadcastOnDisconnect() {
val tracker = makeTracker()
val mobileNai1 = mock(NetworkAgentInfo::class.java)
val mobileNai2 = mock(NetworkAgentInfo::class.java)
doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai1)
mTracker.add(TYPE_MOBILE, mobileNai1)
tracker.add(TYPE_MOBILE, mobileNai1)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, CONNECTED, TYPE_MOBILE)
reset(mMockService)
doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai2)
mTracker.add(TYPE_MOBILE, mobileNai2)
tracker.add(TYPE_MOBILE, mobileNai2)
verify(mMockService, never()).sendLegacyNetworkBroadcast(any(), any(), anyInt())
mTracker.remove(TYPE_MOBILE, mobileNai1, false /* wasDefault */)
tracker.remove(TYPE_MOBILE, mobileNai1, false /* wasDefault */)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, DISCONNECTED, TYPE_MOBILE)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai2, CONNECTED, TYPE_MOBILE)
}