From a9dda298748ea1cd288e1cd41f8a487ebff707a5 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Thu, 21 May 2020 09:15:44 -0700 Subject: [PATCH 1/3] CTS test ConnectivityDiagnostics via CarrierPrivilegesTracker. This change adds a CTS test for ConnectivityDiagnostics using CarrierPrivilegesTracker to receive permissions for ConnectivityDiagnostics callbacks. Specifically, the test provides CarrierPrivileges to the test package (android.net.cts) for the active subscription via Carrier Configs overrides. CarrierPrivilegesTracker listens to the Carrier Configs change and matches the loaded certificate with the test package, then includes the test package UID as an administrator for the Network in ConnectivityService. Then, a ConnectivityDiagnosticsCallback is registered and receives a ConnectivityReport on register for the active subscription. Bug: 148032944 Bug: 151332031 Test: atest ConnectivityDiagnosticsManagerTest Change-Id: Iee8a428ada0b6e2127410267a13c3b688df83e6d Merged-In: Iee8a428ada0b6e2127410267a13c3b688df83e6d --- .../ConnectivityDiagnosticsManagerTest.java | 166 +++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) diff --git a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java index d17d8e53ae..1e64d83a17 100644 --- a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java +++ b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java @@ -16,6 +16,7 @@ package android.net.cts; +import static android.content.pm.PackageManager.FEATURE_TELEPHONY; import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback; import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK; @@ -31,6 +32,7 @@ import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP import static android.net.ConnectivityDiagnosticsManager.persistableBundleEquals; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static android.net.cts.util.CtsNetUtils.TestNetworkCallback; @@ -41,9 +43,15 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; import android.annotation.NonNull; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.net.ConnectivityDiagnosticsManager; import android.net.ConnectivityManager; import android.net.LinkAddress; @@ -58,10 +66,15 @@ import android.os.IBinder; import android.os.PersistableBundle; import android.os.Process; import android.platform.test.annotations.AppModeFull; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; import android.util.Pair; import androidx.test.InstrumentationRegistry; +import com.android.internal.telephony.uicc.IccUtils; +import com.android.internal.util.ArrayUtils; import com.android.testutils.ArrayTrackRecord; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import com.android.testutils.DevSdkIgnoreRunner; @@ -71,7 +84,10 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.security.MessageDigest; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; @RunWith(DevSdkIgnoreRunner.class) @IgnoreUpTo(Build.VERSION_CODES.Q) // ConnectivityDiagnosticsManager did not exist in Q @@ -85,6 +101,7 @@ public class ConnectivityDiagnosticsManagerTest { private static final int FAIL_RATE_PERCENTAGE = 100; private static final int UNKNOWN_DETECTION_METHOD = 4; private static final int FILTERED_UNKNOWN_DETECTION_METHOD = 0; + private static final int CARRIER_CONFIG_CHANGED_BROADCAST_TIMEOUT = 5000; private static final Executor INLINE_EXECUTOR = x -> x.run(); @@ -95,15 +112,23 @@ public class ConnectivityDiagnosticsManagerTest { .removeCapability(NET_CAPABILITY_NOT_VPN) .build(); + private static final String SHA_256 = "SHA-256"; + // Callback used to keep TestNetworks up when there are no other outstanding NetworkRequests // for it. private static final TestNetworkCallback TEST_NETWORK_CALLBACK = new TestNetworkCallback(); + private static final NetworkRequest CELLULAR_NETWORK_REQUEST = + new NetworkRequest.Builder().addTransportType(TRANSPORT_CELLULAR).build(); + private static final IBinder BINDER = new Binder(); private Context mContext; private ConnectivityManager mConnectivityManager; private ConnectivityDiagnosticsManager mCdm; + private CarrierConfigManager mCarrierConfigManager; + private PackageManager mPackageManager; + private TelephonyManager mTelephonyManager; private Network mTestNetwork; @Before @@ -111,6 +136,9 @@ public class ConnectivityDiagnosticsManagerTest { mContext = InstrumentationRegistry.getContext(); mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); mCdm = mContext.getSystemService(ConnectivityDiagnosticsManager.class); + mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); + mPackageManager = mContext.getPackageManager(); + mTelephonyManager = mContext.getSystemService(TelephonyManager.class); mConnectivityManager.requestNetwork(TEST_NETWORK_REQUEST, TEST_NETWORK_CALLBACK); } @@ -141,6 +169,98 @@ public class ConnectivityDiagnosticsManagerTest { cb.assertNoCallback(); } + @Test + public void testRegisterCallbackWithCarrierPrivileges() throws Exception { + assumeTrue(mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)); + + final int subId = SubscriptionManager.getDefaultSubscriptionId(); + if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + fail("Need an active subscription. Please ensure that the device has working mobile" + + " data."); + } + + final CarrierConfigReceiver carrierConfigReceiver = new CarrierConfigReceiver(subId); + mContext.registerReceiver( + carrierConfigReceiver, + new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); + + final TestNetworkCallback testNetworkCallback = new TestNetworkCallback(); + final TestConnectivityDiagnosticsCallback connDiagsCallback = + new TestConnectivityDiagnosticsCallback(); + try { + doBroadcastCarrierConfigsAndVerifyOnConnectivityReportAvailable( + subId, carrierConfigReceiver, testNetworkCallback, connDiagsCallback); + } finally { + runWithShellPermissionIdentity( + () -> mCarrierConfigManager.overrideConfig(subId, null), + android.Manifest.permission.MODIFY_PHONE_STATE); + mConnectivityManager.unregisterNetworkCallback(testNetworkCallback); + mCdm.unregisterConnectivityDiagnosticsCallback(connDiagsCallback); + mContext.unregisterReceiver(carrierConfigReceiver); + } + } + + private String getCertHashForThisPackage() throws Exception { + final PackageInfo pkgInfo = + mPackageManager.getPackageInfo( + mContext.getOpPackageName(), PackageManager.GET_SIGNATURES); + final MessageDigest md = MessageDigest.getInstance(SHA_256); + final byte[] certHash = md.digest(pkgInfo.signatures[0].toByteArray()); + return IccUtils.bytesToHexString(certHash); + } + + private void doBroadcastCarrierConfigsAndVerifyOnConnectivityReportAvailable( + int subId, + @NonNull CarrierConfigReceiver carrierConfigReceiver, + @NonNull TestNetworkCallback testNetworkCallback, + @NonNull TestConnectivityDiagnosticsCallback connDiagsCallback) + throws Exception { + final PersistableBundle carrierConfigs = new PersistableBundle(); + carrierConfigs.putStringArray( + CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY, + new String[] {getCertHashForThisPackage()}); + + runWithShellPermissionIdentity( + () -> { + mCarrierConfigManager.overrideConfig(subId, carrierConfigs); + mCarrierConfigManager.notifyConfigChangedForSubId(subId); + }, + android.Manifest.permission.MODIFY_PHONE_STATE); + + // TODO(b/157779832): This should use android.permission.CHANGE_NETWORK_STATE. However, the + // shell does not have CHANGE_NETWORK_STATE, so use CONNECTIVITY_INTERNAL until the shell + // permissions are updated. + runWithShellPermissionIdentity( + () -> mConnectivityManager.requestNetwork( + CELLULAR_NETWORK_REQUEST, testNetworkCallback), + android.Manifest.permission.CONNECTIVITY_INTERNAL); + + final Network network = testNetworkCallback.waitForAvailable(); + assertNotNull(network); + + assertTrue("Didn't receive broadcast for ACTION_CARRIER_CONFIG_CHANGED for subId=" + subId, + carrierConfigReceiver.waitForCarrierConfigChanged()); + assertTrue("Don't have Carrier Privileges after adding cert for this package", + mTelephonyManager.createForSubscriptionId(subId).hasCarrierPrivileges()); + + // Wait for CarrierPrivilegesTracker to receive the ACTION_CARRIER_CONFIG_CHANGED + // broadcast. CPT then needs to update the corresponding DataConnection, which then + // updates ConnectivityService. Unfortunately, this update to the NetworkCapabilities in + // CS does not trigger NetworkCallback#onCapabilitiesChanged as changing the + // administratorUids is not a publicly visible change. In lieu of a better signal to + // detministically wait for, use Thread#sleep here. + Thread.sleep(500); + + mCdm.registerConnectivityDiagnosticsCallback( + CELLULAR_NETWORK_REQUEST, INLINE_EXECUTOR, connDiagsCallback); + + final String interfaceName = + mConnectivityManager.getLinkProperties(network).getInterfaceName(); + connDiagsCallback.expectOnConnectivityReportAvailable( + network, interfaceName, TRANSPORT_CELLULAR); + connDiagsCallback.assertNoCallback(); + } + @Test public void testRegisterDuplicateConnectivityDiagnosticsCallback() { final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback(); @@ -326,13 +446,18 @@ public class ConnectivityDiagnosticsManagerTest { public void expectOnConnectivityReportAvailable( @NonNull Network network, @NonNull String interfaceName) { + expectOnConnectivityReportAvailable(network, interfaceName, TRANSPORT_TEST); + } + + public void expectOnConnectivityReportAvailable( + @NonNull Network network, @NonNull String interfaceName, int transportType) { final ConnectivityReport result = (ConnectivityReport) mHistory.poll(CALLBACK_TIMEOUT_MILLIS, x -> true); assertEquals(network, result.getNetwork()); final NetworkCapabilities nc = result.getNetworkCapabilities(); assertNotNull(nc); - assertTrue(nc.hasTransport(TRANSPORT_TEST)); + assertTrue(nc.hasTransport(transportType)); assertNotNull(result.getLinkProperties()); assertEquals(interfaceName, result.getLinkProperties().getInterfaceName()); @@ -386,4 +511,43 @@ public class ConnectivityDiagnosticsManagerTest { mHistory.poll(NO_CALLBACK_INVOKED_TIMEOUT, x -> true)); } } + + private class CarrierConfigReceiver extends BroadcastReceiver { + private final CountDownLatch mLatch = new CountDownLatch(1); + private final int mSubId; + + CarrierConfigReceiver(int subId) { + mSubId = subId; + } + + @Override + public void onReceive(Context context, Intent intent) { + if (!CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) { + return; + } + + final int subId = + intent.getIntExtra( + CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + if (mSubId != subId) return; + + final PersistableBundle carrierConfigs = mCarrierConfigManager.getConfigForSubId(subId); + if (!CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfigs)) return; + + final String[] certs = + carrierConfigs.getStringArray( + CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY); + try { + if (ArrayUtils.contains(certs, getCertHashForThisPackage())) { + mLatch.countDown(); + } + } catch (Exception e) { + } + } + + boolean waitForCarrierConfigChanged() throws Exception { + return mLatch.await(CARRIER_CONFIG_CHANGED_BROADCAST_TIMEOUT, TimeUnit.MILLISECONDS); + } + } } From 6261d27a9f5c8a30d2a1afb089bb66794e9b0bce Mon Sep 17 00:00:00 2001 From: Luke Huang Date: Sat, 20 Jun 2020 11:49:40 +0800 Subject: [PATCH 2/3] Add net-utils-framework-common to cts-net In order to avoid class package missing problem, add net-utils-framework-common in cts net test build. Also jarjar the package name to prevent conflict. Test: build Test: atest DnsResolverTest Bug: 150952393 Change-Id: I40e2d4c4945a0579f6e1923e4722b09354ff050c --- tests/cts/net/Android.bp | 7 ++++--- tests/cts/net/jarjar-rules-shared.txt | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 tests/cts/net/jarjar-rules-shared.txt diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp index 2b99a40202..112799b716 100644 --- a/tests/cts/net/Android.bp +++ b/tests/cts/net/Android.bp @@ -36,19 +36,20 @@ java_defaults { "src/**/*.java", "src/**/*.kt", ], - + jarjar_rules: "jarjar-rules-shared.txt", static_libs: [ "FrameworksNetCommonTests", "TestNetworkStackLib", - "core-tests-support", "compatibility-device-util-axt", + "core-tests-support", "cts-net-utils", "ctstestrunner-axt", "ctstestserver", - "mockwebserver", "junit", "junit-params", "libnanohttpd", + "mockwebserver", + "net-utils-framework-common", "truth-prebuilt", ], diff --git a/tests/cts/net/jarjar-rules-shared.txt b/tests/cts/net/jarjar-rules-shared.txt new file mode 100644 index 0000000000..11dba74096 --- /dev/null +++ b/tests/cts/net/jarjar-rules-shared.txt @@ -0,0 +1,2 @@ +# Module library in frameworks/libs/net +rule com.android.net.module.util.** android.net.cts.util.@1 \ No newline at end of file From cce29fc44df22478eca67480d56ee1ea17345c18 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Fri, 29 May 2020 12:08:15 -0700 Subject: [PATCH 3/3] Fix ConnDiags Test for invoke-after-validate and unregister CBs. This change fixes several things in ConnectivityDiagnosticsManagerTest: - testOnConnectivityReportAvailable creates the Test Network after registering the ConnectivityDiagnosticsCallback. This ensures that the callback is invoked only after the network is validated (not for the on-register behavior). - The TestNetworkInterface created while setting up the Test Network is held onto for the duration of each test. This ensures that the interface is not garbage collected during the test. While the interface is not needed for the test, this change makes it clear when the interface is cleaned up. - All registered ConnectivityDiagnosticsCallbacks are unregistered at the end of each test. This ensures that all accompanying NetworkRequests are cleaned up. If NetworkRequests are leaked, unrelated test failures can occur (the platform limits the number of NetworkRequests per UID). Bug: 156294356 Bug: 148032944 Test: atest android.net.cts.ConnectivityDiagnosticsManagerTest Change-Id: I1836536fe60a65ba33170cd80e8f4996f1965d19 --- .../ConnectivityDiagnosticsManagerTest.java | 101 ++++++++++-------- 1 file changed, 58 insertions(+), 43 deletions(-) diff --git a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java index 1e64d83a17..a19ba64d7f 100644 --- a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java +++ b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java @@ -36,6 +36,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static android.net.cts.util.CtsNetUtils.TestNetworkCallback; +import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity; import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; import static org.junit.Assert.assertEquals; @@ -63,6 +64,7 @@ import android.net.TestNetworkManager; import android.os.Binder; import android.os.Build; import android.os.IBinder; +import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.Process; import android.platform.test.annotations.AppModeFull; @@ -85,6 +87,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; @@ -114,10 +118,6 @@ public class ConnectivityDiagnosticsManagerTest { private static final String SHA_256 = "SHA-256"; - // Callback used to keep TestNetworks up when there are no other outstanding NetworkRequests - // for it. - private static final TestNetworkCallback TEST_NETWORK_CALLBACK = new TestNetworkCallback(); - private static final NetworkRequest CELLULAR_NETWORK_REQUEST = new NetworkRequest.Builder().addTransportType(TRANSPORT_CELLULAR).build(); @@ -129,7 +129,14 @@ public class ConnectivityDiagnosticsManagerTest { private CarrierConfigManager mCarrierConfigManager; private PackageManager mPackageManager; private TelephonyManager mTelephonyManager; + + // Callback used to keep TestNetworks up when there are no other outstanding NetworkRequests + // for it. + private TestNetworkCallback mTestNetworkCallback; private Network mTestNetwork; + private ParcelFileDescriptor mTestNetworkFD; + + private List mRegisteredCallbacks; @Before public void setUp() throws Exception { @@ -140,27 +147,40 @@ public class ConnectivityDiagnosticsManagerTest { mPackageManager = mContext.getPackageManager(); mTelephonyManager = mContext.getSystemService(TelephonyManager.class); - mConnectivityManager.requestNetwork(TEST_NETWORK_REQUEST, TEST_NETWORK_CALLBACK); + mTestNetworkCallback = new TestNetworkCallback(); + mConnectivityManager.requestNetwork(TEST_NETWORK_REQUEST, mTestNetworkCallback); + + mRegisteredCallbacks = new ArrayList<>(); } @After public void tearDown() throws Exception { - mConnectivityManager.unregisterNetworkCallback(TEST_NETWORK_CALLBACK); - + mConnectivityManager.unregisterNetworkCallback(mTestNetworkCallback); if (mTestNetwork != null) { runWithShellPermissionIdentity(() -> { final TestNetworkManager tnm = mContext.getSystemService(TestNetworkManager.class); tnm.teardownTestNetwork(mTestNetwork); }); + mTestNetwork = null; + } + + if (mTestNetworkFD != null) { + mTestNetworkFD.close(); + mTestNetworkFD = null; + } + + for (TestConnectivityDiagnosticsCallback cb : mRegisteredCallbacks) { + mCdm.unregisterConnectivityDiagnosticsCallback(cb); } } @Test public void testRegisterConnectivityDiagnosticsCallback() throws Exception { - mTestNetwork = setUpTestNetwork(); + mTestNetworkFD = setUpTestNetwork().getFileDescriptor(); + mTestNetwork = mTestNetworkCallback.waitForAvailable(); - final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback(); - mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb); + final TestConnectivityDiagnosticsCallback cb = + createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST); final String interfaceName = mConnectivityManager.getLinkProperties(mTestNetwork).getInterfaceName(); @@ -185,17 +205,15 @@ public class ConnectivityDiagnosticsManagerTest { new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); final TestNetworkCallback testNetworkCallback = new TestNetworkCallback(); - final TestConnectivityDiagnosticsCallback connDiagsCallback = - new TestConnectivityDiagnosticsCallback(); + try { doBroadcastCarrierConfigsAndVerifyOnConnectivityReportAvailable( - subId, carrierConfigReceiver, testNetworkCallback, connDiagsCallback); + subId, carrierConfigReceiver, testNetworkCallback); } finally { runWithShellPermissionIdentity( () -> mCarrierConfigManager.overrideConfig(subId, null), android.Manifest.permission.MODIFY_PHONE_STATE); mConnectivityManager.unregisterNetworkCallback(testNetworkCallback); - mCdm.unregisterConnectivityDiagnosticsCallback(connDiagsCallback); mContext.unregisterReceiver(carrierConfigReceiver); } } @@ -212,8 +230,7 @@ public class ConnectivityDiagnosticsManagerTest { private void doBroadcastCarrierConfigsAndVerifyOnConnectivityReportAvailable( int subId, @NonNull CarrierConfigReceiver carrierConfigReceiver, - @NonNull TestNetworkCallback testNetworkCallback, - @NonNull TestConnectivityDiagnosticsCallback connDiagsCallback) + @NonNull TestNetworkCallback testNetworkCallback) throws Exception { final PersistableBundle carrierConfigs = new PersistableBundle(); carrierConfigs.putStringArray( @@ -251,8 +268,8 @@ public class ConnectivityDiagnosticsManagerTest { // detministically wait for, use Thread#sleep here. Thread.sleep(500); - mCdm.registerConnectivityDiagnosticsCallback( - CELLULAR_NETWORK_REQUEST, INLINE_EXECUTOR, connDiagsCallback); + final TestConnectivityDiagnosticsCallback connDiagsCallback = + createAndRegisterConnectivityDiagnosticsCallback(CELLULAR_NETWORK_REQUEST); final String interfaceName = mConnectivityManager.getLinkProperties(network).getInterfaceName(); @@ -263,8 +280,8 @@ public class ConnectivityDiagnosticsManagerTest { @Test public void testRegisterDuplicateConnectivityDiagnosticsCallback() { - final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback(); - mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb); + final TestConnectivityDiagnosticsCallback cb = + createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST); try { mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb); @@ -288,10 +305,11 @@ public class ConnectivityDiagnosticsManagerTest { @Test public void testOnConnectivityReportAvailable() throws Exception { - mTestNetwork = setUpTestNetwork(); + final TestConnectivityDiagnosticsCallback cb = + createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST); - final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback(); - mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb); + mTestNetworkFD = setUpTestNetwork().getFileDescriptor(); + mTestNetwork = mTestNetworkCallback.waitForAvailable(); final String interfaceName = mConnectivityManager.getLinkProperties(mTestNetwork).getInterfaceName(); @@ -339,10 +357,11 @@ public class ConnectivityDiagnosticsManagerTest { long timestampMillis, @NonNull PersistableBundle extras) throws Exception { - mTestNetwork = setUpTestNetwork(); + mTestNetworkFD = setUpTestNetwork().getFileDescriptor(); + mTestNetwork = mTestNetworkCallback.waitForAvailable(); - final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback(); - mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb); + final TestConnectivityDiagnosticsCallback cb = + createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST); final String interfaceName = mConnectivityManager.getLinkProperties(mTestNetwork).getInterfaceName(); @@ -370,10 +389,11 @@ public class ConnectivityDiagnosticsManagerTest { } private void verifyOnNetworkConnectivityReported(boolean hasConnectivity) throws Exception { - mTestNetwork = setUpTestNetwork(); + mTestNetworkFD = setUpTestNetwork().getFileDescriptor(); + mTestNetwork = mTestNetworkCallback.waitForAvailable(); - final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback(); - mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb); + final TestConnectivityDiagnosticsCallback cb = + createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST); // onConnectivityReportAvailable always invoked when the test network is established final String interfaceName = @@ -394,17 +414,12 @@ public class ConnectivityDiagnosticsManagerTest { cb.assertNoCallback(); } - @NonNull - private Network waitForConnectivityServiceIdleAndGetNetwork() throws InterruptedException { - // Get a new Network. This requires going through the ConnectivityService thread. Once it - // completes, all previously enqueued messages on the ConnectivityService main Handler have - // completed. - final TestNetworkCallback callback = new TestNetworkCallback(); - mConnectivityManager.requestNetwork(TEST_NETWORK_REQUEST, callback); - final Network network = callback.waitForAvailable(); - mConnectivityManager.unregisterNetworkCallback(callback); - assertNotNull(network); - return network; + private TestConnectivityDiagnosticsCallback createAndRegisterConnectivityDiagnosticsCallback( + NetworkRequest request) { + final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback(); + mCdm.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, cb); + mRegisteredCallbacks.add(cb); + return cb; } /** @@ -412,16 +427,16 @@ public class ConnectivityDiagnosticsManagerTest { * to the Network being validated. */ @NonNull - private Network setUpTestNetwork() throws Exception { + private TestNetworkInterface setUpTestNetwork() throws Exception { final int[] administratorUids = new int[] {Process.myUid()}; - runWithShellPermissionIdentity( + return callWithShellPermissionIdentity( () -> { final TestNetworkManager tnm = mContext.getSystemService(TestNetworkManager.class); final TestNetworkInterface tni = tnm.createTunInterface(new LinkAddress[0]); tnm.setupTestNetwork(tni.getInterfaceName(), administratorUids, BINDER); + return tni; }); - return waitForConnectivityServiceIdleAndGetNetwork(); } private static class TestConnectivityDiagnosticsCallback