diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index 6113ef3941..15b666a6eb 100644 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -2223,7 +2223,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @NonNull public List getAllNetworkStateSnapshots() { // This contains IMSI details, so make sure the caller is privileged. - PermissionUtils.enforceNetworkStackPermission(mContext); + enforceNetworkStackOrSettingsPermission(); final ArrayList result = new ArrayList<>(); for (Network network : getAllNetworks()) { diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java index 33f704f5cf..0075b54716 100644 --- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java +++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java @@ -74,9 +74,11 @@ import static com.android.testutils.TestPermissionUtil.runAsShell; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; @@ -107,9 +109,12 @@ import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkInfo.State; import android.net.NetworkRequest; +import android.net.NetworkSpecifier; +import android.net.NetworkStateSnapshot; import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.SocketKeepalive; +import android.net.TelephonyNetworkSpecifier; import android.net.TestNetworkInterface; import android.net.TestNetworkManager; import android.net.TetheringManager; @@ -128,6 +133,7 @@ import android.os.UserHandle; import android.os.VintfRuntimeInfo; import android.platform.test.annotations.AppModeFull; import android.provider.Settings; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArraySet; @@ -178,6 +184,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; @@ -439,6 +446,68 @@ public class ConnectivityManagerTest { } } + private String getSubscriberIdForCellNetwork(Network cellNetwork) { + final NetworkCapabilities cellCaps = mCm.getNetworkCapabilities(cellNetwork); + final NetworkSpecifier specifier = cellCaps.getNetworkSpecifier(); + assertTrue(specifier instanceof TelephonyNetworkSpecifier); + // Get subscription from Telephony network specifier. + final int subId = ((TelephonyNetworkSpecifier) specifier).getSubscriptionId(); + assertNotEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, subId); + + // Get subscriber Id from telephony manager. + final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); + return runWithShellPermissionIdentity(() -> tm.getSubscriberId(subId), + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE); + } + + @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) + @Test + public void testGetAllNetworkStateSnapshots() + throws InterruptedException { + // Make sure cell is active to retrieve IMSI for verification in later step. + final Network cellNetwork = mCtsNetUtils.connectToCell(); + final String subscriberId = getSubscriberIdForCellNetwork(cellNetwork); + assertFalse(TextUtils.isEmpty(subscriberId)); + + // Verify the API cannot be called without proper permission. + assertThrows(SecurityException.class, () -> mCm.getAllNetworkStateSnapshots()); + + // Get all networks, verify the result of getAllNetworkStateSnapshots matches the result + // got from other APIs. + final Network[] networks = mCm.getAllNetworks(); + assertGreaterOrEqual(networks.length, 1); + final List snapshots = runWithShellPermissionIdentity( + () -> mCm.getAllNetworkStateSnapshots(), NETWORK_SETTINGS); + assertEquals(networks.length, snapshots.size()); + for (final Network network : networks) { + // Can't use a lambda because it will cause the test to crash on R with + // NoClassDefFoundError. + NetworkStateSnapshot snapshot = null; + for (NetworkStateSnapshot item : snapshots) { + if (item.getNetwork().equals(network)) { + snapshot = item; + break; + } + } + assertNotNull(snapshot); + final NetworkCapabilities caps = + Objects.requireNonNull(mCm.getNetworkCapabilities(network)); + // Redact specifier of the capabilities of the snapshot before comparing since + // the result returned from getNetworkCapabilities always get redacted. + final NetworkSpecifier redactedSnapshotCapSpecifier = + snapshot.getNetworkCapabilities().getNetworkSpecifier().redact(); + assertEquals("", caps.describeImmutableDifferences( + snapshot.getNetworkCapabilities() + .setNetworkSpecifier(redactedSnapshotCapSpecifier))); + assertEquals(mCm.getLinkProperties(network), snapshot.getLinkProperties()); + assertEquals(mCm.getNetworkInfo(network).getType(), snapshot.getLegacyType()); + + if (network.equals(cellNetwork)) { + assertEquals(subscriberId, snapshot.getSubscriberId()); + } + } + } + /** * Tests that connections can be opened on WiFi and cellphone networks, * and that they are made from different IP addresses. diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt index 1a75a7fa79..8e2b3101ed 100644 --- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt +++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt @@ -15,6 +15,7 @@ */ package android.net.cts +import android.Manifest.permission.NETWORK_SETTINGS import android.app.Instrumentation import android.content.Context import android.net.ConnectivityManager @@ -71,6 +72,8 @@ import android.os.Message import android.os.SystemClock import android.util.DebugUtils.valueToString import androidx.test.InstrumentationRegistry +import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity +import com.android.compatibility.common.util.ThrowingSupplier import com.android.modules.utils.build.SdkLevel import com.android.net.module.util.ArrayTrackRecord import com.android.testutils.CompatUtil @@ -332,7 +335,8 @@ class NetworkAgentTest { context: Context = realContext, name: String? = null, initialNc: NetworkCapabilities? = null, - initialLp: LinkProperties? = null + initialLp: LinkProperties? = null, + initialConfig: NetworkAgentConfig? = null ): TestableNetworkAgent { val nc = initialNc ?: NetworkCapabilities().apply { addTransportType(TRANSPORT_TEST) @@ -352,7 +356,7 @@ class NetworkAgentTest { addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 32)) addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null)) } - val config = NetworkAgentConfig.Builder().build() + val config = initialConfig ?: NetworkAgentConfig.Builder().build() return TestableNetworkAgent(context, mHandlerThread.looper, nc, lp, config).also { agentsToCleanUp.add(it) } @@ -845,4 +849,29 @@ class NetworkAgentTest { callbackWeaker.assertNoCallback(expectedRemainingLingerDuration) callbackWeaker.expectCallback(agent1.network!!) } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.R) + fun testSetSubscriberId() { + val name = "TEST-AGENT" + val imsi = UUID.randomUUID().toString() + val config = NetworkAgentConfig.Builder().setSubscriberId(imsi).build() + + val request: NetworkRequest = NetworkRequest.Builder() + .clearCapabilities() + .addTransportType(TRANSPORT_TEST) + .setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(name)) + .build() + val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) + requestNetwork(request, callback) + + val agent = createNetworkAgent(name = name, initialConfig = config) + agent.register() + agent.markConnected() + callback.expectAvailableThenValidatedCallbacks(agent.network!!) + val snapshots = runWithShellPermissionIdentity(ThrowingSupplier { + mCM!!.allNetworkStateSnapshots }, NETWORK_SETTINGS) + val testNetworkSnapshot = snapshots.findLast { it.network == agent.network } + assertEquals(imsi, testNetworkSnapshot!!.subscriberId) + } }