Implement matching semantics for L2capNetworkSpecifier

A server network is created by using ConnectivityManger#reserveNetwork,
in which the app passes a specifier that sets:

reservationRequest = {
    role = server
    headerCompression = 6lowpan
    remoteAddr = any (null)
    psm = any
}

This specifier must subsequently match the blanket reservation offer,
and the reserved offer that is generated as a response:

blanketOffer = {
    role = server
    headerCompression = any
    remoteAddr = any (null)
    psm = any
}

reservedOffer = {
    role = server
    headerCompression = 6lowpan
    remoteAddr = any (null)
    psm = 0x81
}

And not the client network offer or a client network:

clientOffer = {
    role = client
    headerCompression = any
    remoteAddr = any (null)
    psm = any
}

clientNetwork = {
    role = client
    headerCompression = 6lowpan
    remoteAddr = 01:02:03:04:05:06
    psm = 0x81
}

Similarly the client request must match both the clientOffer and
clientNetweork, but not the reservedOffer (and technically
blanketOffer):

clientRequest = {
    role = client
    headerCompression = 6lowpan
    remoteAddr = 01:02:03:04:05:06
    psm = 0x81
}

Note, a request for TRANSPORT_BLUETOOTH with no specifier matches *any*
specifier per specifier matching semantics in NetworkCapabilities.

Test: L2capNetworkSpecifierTest
Change-Id: Ia16926b463a54530ae6e88278466e92ed82bf852
This commit is contained in:
Patrick Rohr 2025-01-10 10:32:30 -08:00
commit 74a8f475b2

View file

@ -251,8 +251,29 @@ public final class L2capNetworkSpecifier extends NetworkSpecifier implements Par
/** @hide */
@Override
public boolean canBeSatisfiedBy(NetworkSpecifier other) {
// TODO: implement matching semantics.
return false;
if (!(other instanceof L2capNetworkSpecifier)) return false;
final L2capNetworkSpecifier rhs = (L2capNetworkSpecifier) other;
// A network / offer cannot be ROLE_ANY, but it is added for consistency.
if (mRole != rhs.mRole && mRole != ROLE_ANY && rhs.mRole != ROLE_ANY) {
return false;
}
if (mHeaderCompression != rhs.mHeaderCompression
&& mHeaderCompression != HEADER_COMPRESSION_ANY
&& rhs.mHeaderCompression != HEADER_COMPRESSION_ANY) {
return false;
}
if (!Objects.equals(mRemoteAddress, rhs.mRemoteAddress)
&& mRemoteAddress != null && rhs.mRemoteAddress != null) {
return false;
}
if (mPsm != rhs.mPsm && mPsm != PSM_ANY && rhs.mPsm != PSM_ANY) {
return false;
}
return true;
}
/** @hide */