Make LegacyTypeTracker testable

...and add basic trivial tests for it.

Test: this, and ConnectivityServiceTest
Bug: 62650382
Change-Id: Ie7ca938e6f66f1b15feb6ed93afa0aebb20884ae
This commit is contained in:
Chalard Jean
2019-04-10 23:07:55 +09:00
parent efe4ae92fc
commit de9b8a9d7e
3 changed files with 113 additions and 15 deletions

View File

@@ -47,6 +47,7 @@ import static android.system.OsConstants.IPPROTO_UDP;
import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.BroadcastOptions; import android.app.BroadcastOptions;
import android.app.NotificationManager; import android.app.NotificationManager;
@@ -632,7 +633,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
* the first network for a given type changes, or if the default network * the first network for a given type changes, or if the default network
* changes. * changes.
*/ */
private class LegacyTypeTracker { @VisibleForTesting
static class LegacyTypeTracker {
private static final boolean DBG = true; private static final boolean DBG = true;
private static final boolean VDBG = false; private static final boolean VDBG = false;
@@ -658,10 +660,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
* - dump is thread-safe with respect to concurrent add and remove calls. * - dump is thread-safe with respect to concurrent add and remove calls.
*/ */
private final ArrayList<NetworkAgentInfo> mTypeLists[]; private final ArrayList<NetworkAgentInfo> mTypeLists[];
@NonNull
private final ConnectivityService mService;
public LegacyTypeTracker() { LegacyTypeTracker(@NonNull ConnectivityService service) {
mTypeLists = (ArrayList<NetworkAgentInfo>[]) mService = service;
new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1]; mTypeLists = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
} }
public void addSupportedType(int type) { public void addSupportedType(int type) {
@@ -710,10 +714,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
// Send a broadcast if this is the first network of its type or if it's the default. // Send a broadcast if this is the first network of its type or if it's the default.
final boolean isDefaultNetwork = isDefaultNetwork(nai); final boolean isDefaultNetwork = mService.isDefaultNetwork(nai);
if ((list.size() == 1) || isDefaultNetwork) { if ((list.size() == 1) || isDefaultNetwork) {
maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork); maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork);
sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type); mService.sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type);
} }
} }
@@ -735,15 +739,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (wasFirstNetwork || wasDefault) { if (wasFirstNetwork || wasDefault) {
maybeLogBroadcast(nai, state, type, wasDefault); maybeLogBroadcast(nai, state, type, wasDefault);
sendLegacyNetworkBroadcast(nai, state, type); mService.sendLegacyNetworkBroadcast(nai, state, type);
} }
if (!list.isEmpty() && wasFirstNetwork) { if (!list.isEmpty() && wasFirstNetwork) {
if (DBG) log("Other network available for type " + type + if (DBG) log("Other network available for type " + type +
", sending connected broadcast"); ", sending connected broadcast");
final NetworkAgentInfo replacement = list.get(0); final NetworkAgentInfo replacement = list.get(0);
maybeLogBroadcast(replacement, state, type, isDefaultNetwork(replacement)); maybeLogBroadcast(replacement, state, type, mService.isDefaultNetwork(replacement));
sendLegacyNetworkBroadcast(replacement, state, type); mService.sendLegacyNetworkBroadcast(replacement, state, type);
} }
} }
@@ -758,7 +762,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// send out another legacy broadcast - currently only used for suspend/unsuspend // send out another legacy broadcast - currently only used for suspend/unsuspend
// toggle // toggle
public void update(NetworkAgentInfo nai) { public void update(NetworkAgentInfo nai) {
final boolean isDefault = isDefaultNetwork(nai); final boolean isDefault = mService.isDefaultNetwork(nai);
final DetailedState state = nai.networkInfo.getDetailedState(); final DetailedState state = nai.networkInfo.getDetailedState();
for (int type = 0; type < mTypeLists.length; type++) { for (int type = 0; type < mTypeLists.length; type++) {
final ArrayList<NetworkAgentInfo> list = mTypeLists[type]; final ArrayList<NetworkAgentInfo> list = mTypeLists[type];
@@ -766,7 +770,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
final boolean isFirst = contains && (nai == list.get(0)); final boolean isFirst = contains && (nai == list.get(0));
if (isFirst || contains && isDefault) { if (isFirst || contains && isDefault) {
maybeLogBroadcast(nai, state, type, isDefault); maybeLogBroadcast(nai, state, type, isDefault);
sendLegacyNetworkBroadcast(nai, state, type); mService.sendLegacyNetworkBroadcast(nai, state, type);
} }
} }
} }
@@ -802,7 +806,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
pw.println(); pw.println();
} }
} }
private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(); private final LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(this);
/** /**
* Helper class which parses out priority arguments and dumps sections according to their * Helper class which parses out priority arguments and dumps sections according to their
@@ -5357,7 +5361,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
} }
private boolean isDefaultNetwork(NetworkAgentInfo nai) { @VisibleForTesting
protected boolean isDefaultNetwork(NetworkAgentInfo nai) {
return nai == getDefaultNetwork(); return nai == getDefaultNetwork();
} }
@@ -6565,7 +6570,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
} }
private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) { @VisibleForTesting
protected void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) {
// The NetworkInfo we actually send out has no bearing on the real // The NetworkInfo we actually send out has no bearing on the real
// state of affairs. For example, if the default connection is mobile, // state of affairs. For example, if the default connection is mobile,
// and a request for HIPRI has just gone away, we need to pretend that // and a request for HIPRI has just gone away, we need to pretend that

View File

@@ -64,7 +64,7 @@ java_defaults {
android_test { android_test {
name: "FrameworksNetTests", name: "FrameworksNetTests",
defaults: ["FrameworksNetTests-jni-defaults"], defaults: ["FrameworksNetTests-jni-defaults"],
srcs: ["java/**/*.java"], srcs: ["java/**/*.java", "java/**/*.kt"],
platform_apis: true, platform_apis: true,
test_suites: ["device-tests"], test_suites: ["device-tests"],
certificate: "platform", certificate: "platform",

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2019 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 com.android.server
import android.net.ConnectivityManager.TYPE_ETHERNET
import android.net.ConnectivityManager.TYPE_MOBILE
import android.net.ConnectivityManager.TYPE_WIFI
import android.net.ConnectivityManager.TYPE_WIMAX
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.server.ConnectivityService.LegacyTypeTracker
import com.android.server.connectivity.NetworkAgentInfo
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
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
const val UNSUPPORTED_TYPE = TYPE_WIMAX
@RunWith(AndroidJUnit4::class)
@SmallTest
class LegacyTypeTrackerTest {
private val supportedTypes = arrayOf(TYPE_MOBILE, TYPE_WIFI, TYPE_ETHERNET)
private val mMockService = mock(ConnectivityService::class.java).apply {
doReturn(false).`when`(this).isDefaultNetwork(any())
}
private val mTracker = LegacyTypeTracker(mMockService).apply {
supportedTypes.forEach {
addSupportedType(it)
}
}
@Test
fun testSupportedTypes() {
try {
mTracker.addSupportedType(supportedTypes[0])
fail("Expected IllegalStateException")
} catch (expected: IllegalStateException) {}
supportedTypes.forEach {
assertTrue(mTracker.isTypeSupported(it))
}
assertFalse(mTracker.isTypeSupported(UNSUPPORTED_TYPE))
}
@Test
fun testAddNetwork() {
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)
// 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)
// 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)
// 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)
// Make sure adding a network for an unsupported type does not register it.
mTracker.add(UNSUPPORTED_TYPE, mobileNai)
assertNull(mTracker.getNetworkForType(UNSUPPORTED_TYPE))
}
}