Merge changes Icecb889a,Id06116ad into main

* changes:
  Set the reservationId when a new NetworkRequest is created
  Add reservationId to NetworkCapabilities
This commit is contained in:
Treehugger Robot 2024-12-12 16:08:35 -08:00 • committed by Gerrit Code Review
commit 3a5b37a87c
5 changed files with 158 additions and 8 deletions

View file

@ -359,6 +359,7 @@ public final class NetworkCapabilities implements Parcelable {
mSubIds = new ArraySet<>();
mUnderlyingNetworks = null;
mEnterpriseId = 0;
mReservationId = RES_ID_UNSET;
}
/**
@ -393,6 +394,7 @@ public final class NetworkCapabilities implements Parcelable {
// necessary.
mUnderlyingNetworks = nc.mUnderlyingNetworks;
mEnterpriseId = nc.mEnterpriseId;
mReservationId = nc.mReservationId;
}
/**
@ -2233,7 +2235,8 @@ public final class NetworkCapabilities implements Parcelable {
&& (onlyImmutable || satisfiedByUids(nc))
&& (onlyImmutable || satisfiedBySSID(nc))
&& (onlyImmutable || satisfiedByRequestor(nc))
&& (onlyImmutable || satisfiedBySubscriptionIds(nc)));
&& (onlyImmutable || satisfiedBySubscriptionIds(nc)))
&& satisfiedByReservationId(nc);
}
/**
@ -2347,7 +2350,8 @@ public final class NetworkCapabilities implements Parcelable {
&& equalsAdministratorUids(that)
&& equalsSubscriptionIds(that)
&& equalsUnderlyingNetworks(that)
&& equalsEnterpriseCapabilitiesId(that);
&& equalsEnterpriseCapabilitiesId(that)
&& equalsReservationId(that);
}
@Override
@ -2373,7 +2377,9 @@ public final class NetworkCapabilities implements Parcelable {
+ Arrays.hashCode(mAdministratorUids) * 67
+ Objects.hashCode(mSubIds) * 71
+ Objects.hashCode(mUnderlyingNetworks) * 73
+ mEnterpriseId * 79;
+ mEnterpriseId * 79
+ mReservationId * 83;
}
@Override
@ -2411,6 +2417,7 @@ public final class NetworkCapabilities implements Parcelable {
dest.writeIntArray(CollectionUtils.toIntArray(mSubIds));
dest.writeTypedList(mUnderlyingNetworks);
dest.writeInt(mEnterpriseId & ALL_VALID_ENTERPRISE_IDS);
dest.writeInt(mReservationId);
}
public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR =
@ -2446,6 +2453,7 @@ public final class NetworkCapabilities implements Parcelable {
}
netCap.setUnderlyingNetworks(in.createTypedArrayList(Network.CREATOR));
netCap.mEnterpriseId = in.readInt() & ALL_VALID_ENTERPRISE_IDS;
netCap.mReservationId = in.readInt();
return netCap;
}
@Override
@ -2548,6 +2556,11 @@ public final class NetworkCapabilities implements Parcelable {
NetworkCapabilities::enterpriseIdNameOf, "&");
}
if (mReservationId != RES_ID_UNSET) {
final boolean isReservationOffer = (mReservationId == RES_ID_MATCH_ALL_RESERVATIONS);
sb.append(" ReservationId: ").append(isReservationOffer ? "*" : mReservationId);
}
sb.append(" UnderlyingNetworks: ");
if (mUnderlyingNetworks != null) {
sb.append("[");
@ -2875,6 +2888,65 @@ public final class NetworkCapabilities implements Parcelable {
return false;
}
/**
* The reservation ID used by non-reservable Networks and "regular" NetworkOffers.
*
* Note that {@code NetworkRequest#FIRST_REQUEST_ID} is 1;
* @hide
*/
public static final int RES_ID_UNSET = 0;
/**
* The reservation ID used by special NetworkOffers that handle RESERVATION requests.
*
* NetworkOffers with {@code RES_ID_MATCH_ALL_RESERVATIONS} *only* receive onNetworkNeeded()
* callbacks for {@code NetworkRequest.Type.RESERVATION}.
* @hide
*/
public static final int RES_ID_MATCH_ALL_RESERVATIONS = -1;
/**
* Unique ID that identifies the network reservation.
*/
private int mReservationId;
/**
* Returns the reservation ID
* @hide
*/
public int getReservationId() {
return mReservationId;
}
/**
* Set the reservation ID
* @hide
*/
public void setReservationId(int resId) {
mReservationId = resId;
}
private boolean equalsReservationId(@NonNull NetworkCapabilities nc) {
return mReservationId == nc.mReservationId;
}
private boolean satisfiedByReservationId(@NonNull NetworkCapabilities nc) {
if (mReservationId == RES_ID_UNSET) {
// To maintain regular NetworkRequest semantics, a request with a zero reservationId
// matches an offer or network with any reservationId except MATCH_ALL_RESERVATIONS.
return nc.mReservationId != RES_ID_MATCH_ALL_RESERVATIONS;
}
// A request with a non-zero reservationId matches only an offer or network with that exact
// reservationId (required to match the network that will eventually come up) or
// MATCH_ALL_RESERVATIONS (required to match the blanket reservation offer).
if (nc.mReservationId == RES_ID_MATCH_ALL_RESERVATIONS) {
return true;
}
return mReservationId == nc.mReservationId;
}
/**
* Returns a bitmask of all the applicable redactions (based on the permissions held by the
* receiving app) to be performed on this object.

View file

@ -258,6 +258,12 @@ public class NetworkRequest implements Parcelable {
}
requestId = rId;
networkCapabilities = nc;
if (type == Type.RESERVATION) {
// Conceptually, the reservationId is not related to the requestId; however, the
// requestId fulfills the same uniqueness requirements that are needed for the
// reservationId, so it can be reused for this purpose.
networkCapabilities.setReservationId(rId);
}
this.legacyType = legacyType;
this.type = type;
}

View file

@ -382,6 +382,7 @@ public class NetworkCapabilitiesTest {
netCap.setAllowedUids(allowedUids);
netCap.setSubscriptionIds(Set.of(TEST_SUBID1, TEST_SUBID2));
netCap.setUids(uids);
netCap.setReservationId(42);
}
netCap.setOwnerUid(123);
@ -1493,4 +1494,42 @@ public class NetworkCapabilitiesTest {
// nc1 and nc2 are the same since invalid capability is ignored
assertEquals(nc1, nc2);
}
@Test
public void testReservationIdMatching() {
final NetworkCapabilities requestNc = new NetworkCapabilities();
final NetworkCapabilities reservationNc = new NetworkCapabilities();
reservationNc.setReservationId(42);
final NetworkCapabilities reservedNetworkNc = new NetworkCapabilities(reservationNc);
final NetworkCapabilities otherNetworkNc = new NetworkCapabilities();
final NetworkCapabilities otherReservedNetworkNc = new NetworkCapabilities();
otherReservedNetworkNc.setReservationId(99);
final NetworkCapabilities offerNc = new NetworkCapabilities();
offerNc.setReservationId(NetworkCapabilities.RES_ID_MATCH_ALL_RESERVATIONS);
// A regular request can match any network or offer except one with MATCH_ALL_RESERVATIONS
assertTrue(requestNc.satisfiedByNetworkCapabilities(reservedNetworkNc));
assertTrue(requestNc.satisfiedByNetworkCapabilities(otherNetworkNc));
assertTrue(requestNc.satisfiedByNetworkCapabilities(otherReservedNetworkNc));
assertFalse(requestNc.satisfiedByNetworkCapabilities(offerNc));
// A reservation request can only match the reservedNetwork and the blanket offer.
assertTrue(reservationNc.satisfiedByNetworkCapabilities(reservedNetworkNc));
assertFalse(reservationNc.satisfiedByNetworkCapabilities(otherNetworkNc));
assertFalse(reservationNc.satisfiedByNetworkCapabilities(otherReservedNetworkNc));
assertTrue(reservationNc.satisfiedByNetworkCapabilities(offerNc));
}
@Test @IgnoreUpTo(SC_V2)
public void testReservationIdEquals() {
final NetworkCapabilities nc = new NetworkCapabilities();
nc.setReservationId(42);
final NetworkCapabilities other = new NetworkCapabilities(nc);
assertEquals(nc, other);
nc.setReservationId(43);
assertNotEquals(nc, other);
}
}

View file

@ -16,6 +16,7 @@
package android.net.cts;
import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
@ -554,4 +555,32 @@ public class NetworkRequestTest {
.setBssidPattern(ARBITRARY_ADDRESS, ARBITRARY_ADDRESS)
.build();
}
@Test
@IgnoreUpTo(Build.VERSION_CODES.R)
public void testNetworkReservation() {
final NetworkCapabilities nc = new NetworkCapabilities();
final NetworkCapabilities blanketOffer = new NetworkCapabilities(nc);
blanketOffer.setReservationId(NetworkCapabilities.RES_ID_MATCH_ALL_RESERVATIONS);
final NetworkCapabilities specificOffer = new NetworkCapabilities(nc);
specificOffer.setReservationId(42);
final NetworkCapabilities otherSpecificOffer = new NetworkCapabilities(nc);
otherSpecificOffer.setReservationId(43);
final NetworkCapabilities regularOffer = new NetworkCapabilities(nc);
final NetworkRequest reservationNR = new NetworkRequest(new NetworkCapabilities(nc),
TYPE_NONE, 42 /* rId */, NetworkRequest.Type.RESERVATION);
final NetworkRequest requestNR = new NetworkRequest(new NetworkCapabilities(nc),
TYPE_NONE, 42 /* rId */, NetworkRequest.Type.REQUEST);
assertTrue(reservationNR.canBeSatisfiedBy(blanketOffer));
assertTrue(reservationNR.canBeSatisfiedBy(specificOffer));
assertFalse(reservationNR.canBeSatisfiedBy(otherSpecificOffer));
assertFalse(reservationNR.canBeSatisfiedBy(regularOffer));
assertFalse(requestNR.canBeSatisfiedBy(blanketOffer));
assertTrue(requestNR.canBeSatisfiedBy(specificOffer));
assertTrue(requestNR.canBeSatisfiedBy(otherSpecificOffer));
assertTrue(requestNR.canBeSatisfiedBy(regularOffer));
}
}

View file

@ -22,6 +22,7 @@ import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import android.net.NetworkCapabilities.RES_ID_MATCH_ALL_RESERVATIONS
import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
import android.net.NetworkProvider
import android.net.NetworkRequest
@ -60,22 +61,25 @@ class CSNetworkReservationTest : CSTest() {
context.packageName, context.attributionTag, NetworkCallback.DECLARED_METHODS_ALL)
}
fun NetworkCapabilities.copyWithReservationId(resId: Int) = NetworkCapabilities(this).also {
it.reservationId = resId
}
@Test
fun testReservationTriggersOnNetworkNeeded() {
val provider = NetworkProvider(context, csHandlerThread.looper, "Ethernet provider")
val offerCb = TestableNetworkOfferCallback(TIMEOUT_MS, NO_CB_TIMEOUT_MS)
val blanketOfferCb = TestableNetworkOfferCallback(TIMEOUT_MS, NO_CB_TIMEOUT_MS)
cm.registerNetworkProvider(provider)
provider.registerNetworkOffer(ETHERNET_SCORE, ETHERNET_CAPS, {r -> r.run()}, offerCb)
// TODO: add reservationId to offer, so it doesn't match the default request.
offerCb.expectOnNetworkNeeded(ETHERNET_CAPS)
val blanketCaps = ETHERNET_CAPS.copyWithReservationId(RES_ID_MATCH_ALL_RESERVATIONS)
provider.registerNetworkOffer(ETHERNET_SCORE, blanketCaps, {r -> r.run()}, blanketOfferCb)
val req = NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET).build()
val cb = NetworkCallback()
cm.reserveNetwork(req, cb)
offerCb.expectOnNetworkNeeded(req.networkCapabilities)
blanketOfferCb.expectOnNetworkNeeded(blanketCaps)
// TODO: also test onNetworkUnneeded is called once ConnectivityManager supports the
// reserveNetwork API.