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:
parent
5e61925e51
commit
74a8f475b2
2 changed files with 77 additions and 2 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -18,8 +18,11 @@ package android.net.cts
|
|||
|
||||
import android.net.L2capNetworkSpecifier
|
||||
import android.net.L2capNetworkSpecifier.HEADER_COMPRESSION_6LOWPAN
|
||||
import android.net.L2capNetworkSpecifier.HEADER_COMPRESSION_ANY
|
||||
import android.net.L2capNetworkSpecifier.HEADER_COMPRESSION_NONE
|
||||
import android.net.L2capNetworkSpecifier.PSM_ANY
|
||||
import android.net.L2capNetworkSpecifier.ROLE_CLIENT
|
||||
import android.net.L2capNetworkSpecifier.ROLE_SERVER
|
||||
import android.net.MacAddress
|
||||
import android.os.Build
|
||||
import com.android.testutils.ConnectivityModuleTest
|
||||
|
|
@ -27,6 +30,8 @@ import com.android.testutils.DevSdkIgnoreRule
|
|||
import com.android.testutils.DevSdkIgnoreRunner
|
||||
import com.android.testutils.assertParcelingIsLossless
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
|
|
@ -60,4 +65,53 @@ class L2capNetworkSpecifierTest {
|
|||
assertEquals(123, specifier.getPsm())
|
||||
assertEquals(remoteMac, specifier.getRemoteAddress())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCanBeSatisfiedBy() {
|
||||
val blanketOffer = L2capNetworkSpecifier.Builder()
|
||||
.setRole(ROLE_SERVER)
|
||||
.setHeaderCompression(HEADER_COMPRESSION_ANY)
|
||||
.setPsm(PSM_ANY)
|
||||
.build()
|
||||
|
||||
val reservedOffer = L2capNetworkSpecifier.Builder()
|
||||
.setRole(ROLE_SERVER)
|
||||
.setHeaderCompression(HEADER_COMPRESSION_6LOWPAN)
|
||||
.setPsm(42)
|
||||
.build()
|
||||
|
||||
val clientOffer = L2capNetworkSpecifier.Builder()
|
||||
.setRole(ROLE_CLIENT)
|
||||
.setHeaderCompression(HEADER_COMPRESSION_ANY)
|
||||
.build()
|
||||
|
||||
val serverReservation = L2capNetworkSpecifier.Builder()
|
||||
.setRole(ROLE_SERVER)
|
||||
.setHeaderCompression(HEADER_COMPRESSION_6LOWPAN)
|
||||
.build()
|
||||
|
||||
assertTrue(serverReservation.canBeSatisfiedBy(blanketOffer))
|
||||
assertTrue(serverReservation.canBeSatisfiedBy(reservedOffer))
|
||||
// Note: serverReservation can be filed using reserveNetwork, or it could be a regular
|
||||
// request filed using requestNetwork.
|
||||
assertFalse(serverReservation.canBeSatisfiedBy(clientOffer))
|
||||
|
||||
val clientRequest = L2capNetworkSpecifier.Builder()
|
||||
.setRole(ROLE_CLIENT)
|
||||
.setHeaderCompression(HEADER_COMPRESSION_6LOWPAN)
|
||||
.setRemoteAddress(MacAddress.fromString("00:01:02:03:04:05"))
|
||||
.setPsm(42)
|
||||
.build()
|
||||
|
||||
assertTrue(clientRequest.canBeSatisfiedBy(clientOffer))
|
||||
// Note: the BlanketOffer also includes a RES_ID_MATCH_ALL_RESERVATIONS. Since the
|
||||
// clientRequest is not a reservation, it won't match that request to begin with.
|
||||
assertFalse(clientRequest.canBeSatisfiedBy(blanketOffer))
|
||||
assertFalse(clientRequest.canBeSatisfiedBy(reservedOffer))
|
||||
|
||||
val matchAny = L2capNetworkSpecifier.Builder().build()
|
||||
assertTrue(matchAny.canBeSatisfiedBy(blanketOffer))
|
||||
assertTrue(matchAny.canBeSatisfiedBy(reservedOffer))
|
||||
assertTrue(matchAny.canBeSatisfiedBy(clientOffer))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue