Merge "Add new APIs in NetworkCapabilities to set and get underlying networks"

This commit is contained in:
Lucas Lin
2021-10-18 05:27:59 +00:00
committed by Gerrit Code Review
3 changed files with 137 additions and 6 deletions

View File

@@ -279,6 +279,7 @@ package android.net {
method @Nullable public String getSsid(); method @Nullable public String getSsid();
method @NonNull public java.util.Set<java.lang.Integer> getSubscriptionIds(); method @NonNull public java.util.Set<java.lang.Integer> getSubscriptionIds();
method @NonNull public int[] getTransportTypes(); method @NonNull public int[] getTransportTypes();
method @Nullable public java.util.List<android.net.Network> getUnderlyingNetworks();
method public boolean isPrivateDnsBroken(); method public boolean isPrivateDnsBroken();
method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
field public static final int NET_CAPABILITY_BIP = 31; // 0x1f field public static final int NET_CAPABILITY_BIP = 31; // 0x1f
@@ -309,6 +310,7 @@ package android.net {
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String); method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String);
method @NonNull public android.net.NetworkCapabilities.Builder setSubscriptionIds(@NonNull java.util.Set<java.lang.Integer>); method @NonNull public android.net.NetworkCapabilities.Builder setSubscriptionIds(@NonNull java.util.Set<java.lang.Integer>);
method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo); method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo);
method @NonNull public android.net.NetworkCapabilities.Builder setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
method @NonNull public static android.net.NetworkCapabilities.Builder withoutDefaultCapabilities(); method @NonNull public static android.net.NetworkCapabilities.Builder withoutDefaultCapabilities();
} }

View File

@@ -42,7 +42,10 @@ import com.android.net.module.util.NetworkCapabilitiesUtils;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.StringJoiner; import java.util.StringJoiner;
@@ -129,6 +132,11 @@ public final class NetworkCapabilities implements Parcelable {
// Set to true when private DNS is broken. // Set to true when private DNS is broken.
private boolean mPrivateDnsBroken; private boolean mPrivateDnsBroken;
// Underlying networks, if any. VPNs and VCNs typically have underlying networks.
// This is an unmodifiable list and it will be returned as is in the getter.
@Nullable
private List<Network> mUnderlyingNetworks;
/** /**
* Uid of the app making the request. * Uid of the app making the request.
*/ */
@@ -184,6 +192,7 @@ public final class NetworkCapabilities implements Parcelable {
mRequestorUid = Process.INVALID_UID; mRequestorUid = Process.INVALID_UID;
mRequestorPackageName = null; mRequestorPackageName = null;
mSubIds = new ArraySet<>(); mSubIds = new ArraySet<>();
mUnderlyingNetworks = null;
} }
/** /**
@@ -213,6 +222,9 @@ public final class NetworkCapabilities implements Parcelable {
mRequestorUid = nc.mRequestorUid; mRequestorUid = nc.mRequestorUid;
mRequestorPackageName = nc.mRequestorPackageName; mRequestorPackageName = nc.mRequestorPackageName;
mSubIds = new ArraySet<>(nc.mSubIds); mSubIds = new ArraySet<>(nc.mSubIds);
// mUnderlyingNetworks is an unmodifiable list if non-null, so a defensive copy is not
// necessary.
mUnderlyingNetworks = nc.mUnderlyingNetworks;
} }
/** /**
@@ -698,6 +710,41 @@ public final class NetworkCapabilities implements Parcelable {
setCapabilities(capabilities, new int[] {}); setCapabilities(capabilities, new int[] {});
} }
/**
* Set the underlying networks of this network.
*
* @param networks The underlying networks of this network.
*
* @hide
*/
public void setUnderlyingNetworks(@Nullable List<Network> networks) {
mUnderlyingNetworks =
(networks == null) ? null : Collections.unmodifiableList(new ArrayList<>(networks));
}
/**
* Get the underlying networks of this network. If the caller is not system privileged, this is
* always redacted to null and it will be never useful to the caller.
*
* @return <li>If the list is null, this network hasn't declared underlying networks.</li>
* <li>If the list is empty, this network has declared that it has no underlying
* networks or it doesn't run on any of the available networks.</li>
* <li>The list can contain multiple underlying networks, e.g. a VPN running over
* multiple networks at the same time.</li>
*
* @hide
*/
@SuppressLint("NullableCollection")
@Nullable
@SystemApi
public List<Network> getUnderlyingNetworks() {
return mUnderlyingNetworks;
}
private boolean equalsUnderlyingNetworks(@NonNull NetworkCapabilities nc) {
return Objects.equals(getUnderlyingNetworks(), nc.getUnderlyingNetworks());
}
/** /**
* Tests for the presence of a capability on this instance. * Tests for the presence of a capability on this instance.
* *
@@ -1901,7 +1948,8 @@ public final class NetworkCapabilities implements Parcelable {
&& equalsPrivateDnsBroken(that) && equalsPrivateDnsBroken(that)
&& equalsRequestor(that) && equalsRequestor(that)
&& equalsAdministratorUids(that) && equalsAdministratorUids(that)
&& equalsSubscriptionIds(that); && equalsSubscriptionIds(that)
&& equalsUnderlyingNetworks(that);
} }
@Override @Override
@@ -1924,7 +1972,8 @@ public final class NetworkCapabilities implements Parcelable {
+ Objects.hashCode(mRequestorUid) * 53 + Objects.hashCode(mRequestorUid) * 53
+ Objects.hashCode(mRequestorPackageName) * 59 + Objects.hashCode(mRequestorPackageName) * 59
+ Arrays.hashCode(mAdministratorUids) * 61 + Arrays.hashCode(mAdministratorUids) * 61
+ Objects.hashCode(mSubIds) * 67; + Objects.hashCode(mSubIds) * 67
+ Objects.hashCode(mUnderlyingNetworks) * 71;
} }
@Override @Override
@@ -1959,6 +2008,7 @@ public final class NetworkCapabilities implements Parcelable {
dest.writeInt(mRequestorUid); dest.writeInt(mRequestorUid);
dest.writeString(mRequestorPackageName); dest.writeString(mRequestorPackageName);
dest.writeIntArray(CollectionUtils.toIntArray(mSubIds)); dest.writeIntArray(CollectionUtils.toIntArray(mSubIds));
dest.writeTypedList(mUnderlyingNetworks);
} }
public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR = public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR =
@@ -1987,6 +2037,7 @@ public final class NetworkCapabilities implements Parcelable {
for (int i = 0; i < subIdInts.length; i++) { for (int i = 0; i < subIdInts.length; i++) {
netCap.mSubIds.add(subIdInts[i]); netCap.mSubIds.add(subIdInts[i]);
} }
netCap.setUnderlyingNetworks(in.createTypedArrayList(Network.CREATOR));
return netCap; return netCap;
} }
@Override @Override
@@ -2078,6 +2129,16 @@ public final class NetworkCapabilities implements Parcelable {
sb.append(" SubscriptionIds: ").append(mSubIds); sb.append(" SubscriptionIds: ").append(mSubIds);
} }
if (mUnderlyingNetworks != null && mUnderlyingNetworks.size() > 0) {
sb.append(" Underlying networks: [");
final StringJoiner joiner = new StringJoiner(",");
for (int i = 0; i < mUnderlyingNetworks.size(); i++) {
joiner.add(mUnderlyingNetworks.get(i).toString());
}
sb.append(joiner.toString());
sb.append("]");
}
sb.append("]"); sb.append("]");
return sb.toString(); return sb.toString();
} }
@@ -2795,6 +2856,17 @@ public final class NetworkCapabilities implements Parcelable {
return this; return this;
} }
/**
* Set the underlying networks of this network.
*
* @param networks The underlying networks of this network.
*/
@NonNull
public Builder setUnderlyingNetworks(@Nullable List<Network> networks) {
mCaps.setUnderlyingNetworks(networks);
return this;
}
/** /**
* Builds the instance of the capabilities. * Builds the instance of the capabilities.
* *

View File

@@ -50,6 +50,7 @@ import static android.os.Process.INVALID_UID;
import static com.android.modules.utils.build.SdkLevel.isAtLeastR; import static com.android.modules.utils.build.SdkLevel.isAtLeastR;
import static com.android.modules.utils.build.SdkLevel.isAtLeastS; import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
import static com.android.testutils.MiscAsserts.assertEmpty; import static com.android.testutils.MiscAsserts.assertEmpty;
import static com.android.testutils.MiscAsserts.assertThrows; import static com.android.testutils.MiscAsserts.assertThrows;
import static com.android.testutils.ParcelUtils.assertParcelSane; import static com.android.testutils.ParcelUtils.assertParcelSane;
@@ -84,7 +85,9 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mockito; import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.Set; import java.util.Set;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@@ -342,7 +345,9 @@ public class NetworkCapabilitiesTest {
} }
private void testParcelSane(NetworkCapabilities cap) { private void testParcelSane(NetworkCapabilities cap) {
if (isAtLeastS()) { if (isAtLeastT()) {
assertParcelSane(cap, 17);
} else if (isAtLeastS()) {
assertParcelSane(cap, 16); assertParcelSane(cap, 16);
} else if (isAtLeastR()) { } else if (isAtLeastR()) {
assertParcelSane(cap, 15); assertParcelSane(cap, 15);
@@ -711,6 +716,47 @@ public class NetworkCapabilitiesTest {
} }
} }
@Test
public void testUnderlyingNetworks() {
assumeTrue(isAtLeastT());
final NetworkCapabilities nc = new NetworkCapabilities();
final Network network1 = new Network(100);
final Network network2 = new Network(101);
final ArrayList<Network> inputNetworks = new ArrayList<>();
inputNetworks.add(network1);
inputNetworks.add(network2);
nc.setUnderlyingNetworks(inputNetworks);
final ArrayList<Network> outputNetworks = new ArrayList<>(nc.getUnderlyingNetworks());
assertEquals(network1, outputNetworks.get(0));
assertEquals(network2, outputNetworks.get(1));
nc.setUnderlyingNetworks(null);
assertNull(nc.getUnderlyingNetworks());
}
@Test
public void testEqualsForUnderlyingNetworks() {
assumeTrue(isAtLeastT());
final NetworkCapabilities nc1 = new NetworkCapabilities();
final NetworkCapabilities nc2 = new NetworkCapabilities();
assertEquals(nc1, nc2);
final Network network = new Network(100);
final ArrayList<Network> inputNetworks = new ArrayList<>();
final ArrayList<Network> emptyList = new ArrayList<>();
inputNetworks.add(network);
nc1.setUnderlyingNetworks(inputNetworks);
assertNotEquals(nc1, nc2);
nc2.setUnderlyingNetworks(inputNetworks);
assertEquals(nc1, nc2);
nc1.setUnderlyingNetworks(emptyList);
assertNotEquals(nc1, nc2);
nc2.setUnderlyingNetworks(emptyList);
assertEquals(nc1, nc2);
nc1.setUnderlyingNetworks(null);
assertNotEquals(nc1, nc2);
nc2.setUnderlyingNetworks(null);
assertEquals(nc1, nc2);
}
@Test @Test
public void testSetNetworkSpecifierOnMultiTransportNc() { public void testSetNetworkSpecifierOnMultiTransportNc() {
// Sequence 1: Transport + Transport + NetworkSpecifier // Sequence 1: Transport + Transport + NetworkSpecifier
@@ -1109,7 +1155,7 @@ public class NetworkCapabilitiesTest {
final TransportInfo transportInfo = new TransportInfo() {}; final TransportInfo transportInfo = new TransportInfo() {};
final String ssid = "TEST_SSID"; final String ssid = "TEST_SSID";
final String packageName = "com.google.test.networkcapabilities"; final String packageName = "com.google.test.networkcapabilities";
final NetworkCapabilities nc = new NetworkCapabilities.Builder() final NetworkCapabilities.Builder capBuilder = new NetworkCapabilities.Builder()
.addTransportType(TRANSPORT_WIFI) .addTransportType(TRANSPORT_WIFI)
.addTransportType(TRANSPORT_CELLULAR) .addTransportType(TRANSPORT_CELLULAR)
.removeTransportType(TRANSPORT_CELLULAR) .removeTransportType(TRANSPORT_CELLULAR)
@@ -1125,8 +1171,14 @@ public class NetworkCapabilitiesTest {
.setSignalStrength(signalStrength) .setSignalStrength(signalStrength)
.setSsid(ssid) .setSsid(ssid)
.setRequestorUid(requestUid) .setRequestorUid(requestUid)
.setRequestorPackageName(packageName) .setRequestorPackageName(packageName);
.build(); final Network network1 = new Network(100);
final Network network2 = new Network(101);
final List<Network> inputNetworks = List.of(network1, network2);
if (isAtLeastT()) {
capBuilder.setUnderlyingNetworks(inputNetworks);
}
final NetworkCapabilities nc = capBuilder.build();
assertEquals(1, nc.getTransportTypes().length); assertEquals(1, nc.getTransportTypes().length);
assertEquals(TRANSPORT_WIFI, nc.getTransportTypes()[0]); assertEquals(TRANSPORT_WIFI, nc.getTransportTypes()[0]);
assertTrue(nc.hasCapability(NET_CAPABILITY_EIMS)); assertTrue(nc.hasCapability(NET_CAPABILITY_EIMS));
@@ -1144,6 +1196,11 @@ public class NetworkCapabilitiesTest {
assertEquals(ssid, nc.getSsid()); assertEquals(ssid, nc.getSsid());
assertEquals(requestUid, nc.getRequestorUid()); assertEquals(requestUid, nc.getRequestorUid());
assertEquals(packageName, nc.getRequestorPackageName()); assertEquals(packageName, nc.getRequestorPackageName());
if (isAtLeastT()) {
final List<Network> outputNetworks = nc.getUnderlyingNetworks();
assertEquals(network1, outputNetworks.get(0));
assertEquals(network2, outputNetworks.get(1));
}
// Cannot assign null into NetworkCapabilities.Builder // Cannot assign null into NetworkCapabilities.Builder
try { try {
final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(null); final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(null);