[FUI22] Support getAllNetworkStateSnapshot

Currently, ConnectivityService has getAllNetworkState but it is
not ideal to expose as system API since the plan is to get rid
of NetworkState. Thus, create a new one that returns
NetworkStateSnapshot to fulfill the needs.

Note the original getAllNetworkState cannot be deleted now since
it has @UnsupportedAppUsage annotation.

Test: atest FrameworksNetTests
Bug: 174123988
Change-Id: Icddd434552b0e9ecbc8299e7242ec88cf3145aca
This commit is contained in:
junyulai
2021-03-03 12:09:05 +08:00
parent 33e7f16a5d
commit ebd15164e9
6 changed files with 143 additions and 13 deletions

View File

@@ -6,6 +6,7 @@ package android.net {
}
public class ConnectivityManager {
method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List<android.net.NetworkStateSnapshot> getAllNetworkStateSnapshot();
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);

View File

@@ -1258,6 +1258,25 @@ public class ConnectivityManager {
}
}
/**
* Return a list of {@link NetworkStateSnapshot}s, one for each network that is currently
* connected.
* @hide
*/
@SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK,
android.Manifest.permission.NETWORK_SETTINGS})
@NonNull
public List<NetworkStateSnapshot> getAllNetworkStateSnapshot() {
try {
return mService.getAllNetworkStateSnapshot();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Returns the {@link Network} object currently serving a given type, or
* null if the given type is not connected.

View File

@@ -31,6 +31,7 @@ import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.NetworkStateSnapshot;
import android.net.OemNetworkPreferences;
import android.net.ProxyInfo;
import android.net.UidRange;
@@ -79,6 +80,8 @@ interface IConnectivityManager
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
NetworkState[] getAllNetworkState();
List<NetworkStateSnapshot> getAllNetworkStateSnapshot();
boolean isActiveNetworkMetered();
boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress,

View File

@@ -1890,26 +1890,48 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
// TODO: Consider delete this function or turn it into a no-op method.
@Override
public NetworkState[] getAllNetworkState() {
// This contains IMSI details, so make sure the caller is privileged.
PermissionUtils.enforceNetworkStackPermission(mContext);
final ArrayList<NetworkState> result = new ArrayList<>();
for (Network network : getAllNetworks()) {
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
// TODO: Consider include SUSPENDED networks.
for (NetworkStateSnapshot snapshot : getAllNetworkStateSnapshot()) {
// NetworkStateSnapshot doesn't contain NetworkInfo, so need to fetch it from the
// NetworkAgentInfo.
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(snapshot.network);
if (nai != null && nai.networkInfo.isConnected()) {
// TODO (b/73321673) : NetworkState contains a copy of the
// NetworkCapabilities, which may contain UIDs of apps to which the
// network applies. Should the UIDs be cleared so as not to leak or
// interfere ?
result.add(nai.getNetworkState());
result.add(new NetworkState(new NetworkInfo(nai.networkInfo),
snapshot.linkProperties, snapshot.networkCapabilities, snapshot.network,
snapshot.subscriberId));
}
}
return result.toArray(new NetworkState[result.size()]);
}
@Override
@NonNull
public List<NetworkStateSnapshot> getAllNetworkStateSnapshot() {
// This contains IMSI details, so make sure the caller is privileged.
PermissionUtils.enforceNetworkStackPermission(mContext);
final ArrayList<NetworkStateSnapshot> result = new ArrayList<>();
for (Network network : getAllNetworks()) {
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
// TODO: Consider include SUSPENDED networks, which should be considered as
// temporary shortage of connectivity of a connected network.
if (nai != null && nai.networkInfo.isConnected()) {
// TODO (b/73321673) : NetworkStateSnapshot contains a copy of the
// NetworkCapabilities, which may contain UIDs of apps to which the
// network applies. Should the UIDs be cleared so as not to leak or
// interfere ?
result.add(nai.getNetworkStateSnapshot());
}
}
return result;
}
@Override
public boolean isActiveNetworkMetered() {
enforceAccessPermission();

View File

@@ -35,7 +35,7 @@ import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkMonitorManager;
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.NetworkStateSnapshot;
import android.net.QosCallbackException;
import android.net.QosFilter;
import android.net.QosFilterParcelable;
@@ -890,15 +890,18 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
mScore = score;
}
public NetworkState getNetworkState() {
/**
* Return a {@link NetworkStateSnapshot} for this network.
*/
@NonNull
public NetworkStateSnapshot getNetworkStateSnapshot() {
synchronized (this) {
// Network objects are outwardly immutable so there is no point in duplicating.
// Duplicating also precludes sharing socket factories and connection pools.
final String subscriberId = (networkAgentConfig != null)
? networkAgentConfig.subscriberId : null;
return new NetworkState(new NetworkInfo(networkInfo),
new LinkProperties(linkProperties),
new NetworkCapabilities(networkCapabilities), network, subscriberId);
return new NetworkStateSnapshot(network, new NetworkCapabilities(networkCapabilities),
new LinkProperties(linkProperties), subscriberId, networkInfo.getType());
}
}

View File

@@ -103,6 +103,7 @@ import static com.android.testutils.ConcurrentUtils.await;
import static com.android.testutils.ConcurrentUtils.durationOf;
import static com.android.testutils.ExceptionUtils.ignoreExceptions;
import static com.android.testutils.HandlerUtils.waitForIdleSerialExecutor;
import static com.android.testutils.MiscAsserts.assertContainsAll;
import static com.android.testutils.MiscAsserts.assertContainsExactly;
import static com.android.testutils.MiscAsserts.assertEmpty;
import static com.android.testutils.MiscAsserts.assertLength;
@@ -203,6 +204,7 @@ import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
import android.net.NetworkStackClient;
import android.net.NetworkStateSnapshot;
import android.net.NetworkTestResultParcelable;
import android.net.OemNetworkPreferences;
import android.net.ProxyInfo;
@@ -1662,6 +1664,7 @@ public class ConnectivityServiceTest {
assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
// Test getAllNetworks()
assertEmpty(mCm.getAllNetworks());
assertEmpty(mCm.getAllNetworkStateSnapshot());
}
/**
@@ -10660,4 +10663,83 @@ public class ConnectivityServiceTest {
// default NCs will be unregistered in tearDown
}
@Test
public void testGetAllNetworkStateSnapshot() throws Exception {
verifyNoNetwork();
// Setup test cellular network with specified LinkProperties and NetworkCapabilities,
// verify the content of the snapshot matches.
final LinkProperties cellLp = new LinkProperties();
final LinkAddress myIpv4Addr = new LinkAddress(InetAddress.getByName("192.0.2.129"), 25);
final LinkAddress myIpv6Addr = new LinkAddress(InetAddress.getByName("2001:db8::1"), 64);
cellLp.setInterfaceName("test01");
cellLp.addLinkAddress(myIpv4Addr);
cellLp.addLinkAddress(myIpv6Addr);
cellLp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
cellLp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
cellLp.addRoute(new RouteInfo(myIpv4Addr, null));
cellLp.addRoute(new RouteInfo(myIpv6Addr, null));
final NetworkCapabilities cellNcTemplate = new NetworkCapabilities.Builder()
.addTransportType(TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_MMS).build();
final TestNetworkCallback cellCb = new TestNetworkCallback();
mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
cellCb);
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp, cellNcTemplate);
mCellNetworkAgent.connect(true);
cellCb.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
List<NetworkStateSnapshot> snapshots = mCm.getAllNetworkStateSnapshot();
assertLength(1, snapshots);
// Compose the expected cellular snapshot for verification.
final NetworkCapabilities cellNc =
mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork());
final NetworkStateSnapshot cellSnapshot = new NetworkStateSnapshot(
mCellNetworkAgent.getNetwork(), cellNc, cellLp,
null, ConnectivityManager.TYPE_MOBILE);
assertEquals(cellSnapshot, snapshots.get(0));
// Connect wifi and verify the snapshots.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
waitForIdle();
// Compose the expected wifi snapshot for verification.
final NetworkCapabilities wifiNc =
mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
final NetworkStateSnapshot wifiSnapshot = new NetworkStateSnapshot(
mWiFiNetworkAgent.getNetwork(), wifiNc, new LinkProperties(), null,
ConnectivityManager.TYPE_WIFI);
snapshots = mCm.getAllNetworkStateSnapshot();
assertLength(2, snapshots);
assertContainsAll(snapshots, cellSnapshot, wifiSnapshot);
// Set cellular as suspended, verify the snapshots will not contain suspended networks.
// TODO: Consider include SUSPENDED networks, which should be considered as
// temporary shortage of connectivity of a connected network.
mCellNetworkAgent.suspend();
waitForIdle();
snapshots = mCm.getAllNetworkStateSnapshot();
assertLength(1, snapshots);
assertEquals(wifiSnapshot, snapshots.get(0));
// Disconnect wifi, verify the snapshots contain nothing.
mWiFiNetworkAgent.disconnect();
waitForIdle();
snapshots = mCm.getAllNetworkStateSnapshot();
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertLength(0, snapshots);
mCellNetworkAgent.resume();
waitForIdle();
snapshots = mCm.getAllNetworkStateSnapshot();
assertLength(1, snapshots);
assertEquals(cellSnapshot, snapshots.get(0));
mCellNetworkAgent.disconnect();
waitForIdle();
verifyNoNetwork();
mCm.unregisterNetworkCallback(cellCb);
}
}