avatar: wait for AVDT signaling channel to open
Bug: 329809288
Flag: EXEMPT - test only
Test: atest avatar:'A2dpTest' -v
Change-Id: I6310f56fb873e84ecb91edea8eccf5a0f302d90d
diff --git a/android/pandora/test/a2dp/signaling_channel.py b/android/pandora/test/a2dp/signaling_channel.py
index 437924a..2abab3c 100644
--- a/android/pandora/test/a2dp/signaling_channel.py
+++ b/android/pandora/test/a2dp/signaling_channel.py
@@ -50,12 +50,23 @@
role: RoleType = None
acp_seid: int = 0
int_seid: int = 0
+ channel_opened_future: asyncio.Future[None] | None = None
def __init__(self, connection: bumble.device.Connection):
super().__init__()
self.connection = connection
self.signaling_queue = asyncio.Queue[bytes]()
self.transport_queue = asyncio.Queue[bytes]()
+ self.once('connection', self._on_avdtp_connection)
+
+ def __str__(self):
+ return (f"SignalingChannel(\n"
+ f" Connection: {self.connection},\n"
+ f" role: {self.role},\n"
+ f" acp_seid: {self.acp_seid},\n"
+ f" int_seid: {self.int_seid},\n"
+ f" waiting for channel to open: {self.channel_opened_future is not None}\n"
+ f")")
@classmethod
async def initiate(cls, connection: bumble.device.Connection) -> SignalingChannel:
@@ -69,6 +80,26 @@
channel._accept_signaling_channel()
return channel
+ def _on_avdtp_connection(self) -> None:
+ logger.info("AVDT signaling channel opened")
+ assert self.channel_opened_future
+ self.channel_opened_future.set_result(None)
+
+ async def wait_signaling_channel_connected(self, timeout: float = 5):
+ if (self.role != "acceptor"):
+ raise ValueError("wait_signaling_channel_connected failed. role is not acceptor")
+
+ self.channel_opened_future = asyncio.get_running_loop().create_future()
+ logger.debug("wait_signaling_channel_connected: future gathered")
+
+ try:
+ await asyncio.wait_for(self.channel_opened_future, timeout=timeout)
+ logger.debug("wait_signaling_channel_connected: future cleanup")
+ self.channel_opened_future = None
+ except TimeoutError:
+ raise TimeoutError(
+ "TimeoutError while waiting for AVDT signaling channel to open") from None
+
async def disconnect(self):
if not self.signaling_channel:
raise ValueError("No connected signaling channel")
@@ -90,6 +121,9 @@
async def expect_signal(self,
expected_sig: typing.Union[av.SignalingPacket, type],
timeout: float = 3) -> av.SignalingPacket:
+ if not self.signaling_channel:
+ raise AttributeError("Signaling channel is None")
+
try:
packet = await asyncio.wait_for(self.signaling_queue.get(), timeout=timeout)
sig = av.SignalingPacket.parse_all(packet)
@@ -108,8 +142,7 @@
if isinstance(expected_sig, av.SignalingPacket) and sig != expected_sig:
logger.error("Received unexpected signal")
- logger.error("Expected signal:")
- expected_sig.show()
+ logger.error(f"Expected signal: {expected_sig.__class__.__name__}")
logger.error("Received signal:")
sig.show()
raise ValueError(f"Received unexpected signal")
@@ -119,6 +152,9 @@
return sig
async def expect_media(self, timeout: float = 3.0) -> avdtp.MediaPacket:
+ if not self.transport_channel:
+ raise AttributeError("Transport channel is None")
+
try:
packet = await asyncio.wait_for(self.transport_queue.get(), timeout=timeout)
logger.debug(f"<<< {self.connection.self_address} {self.role} received media <<<")
@@ -160,6 +196,7 @@
spec=l2cap.ClassicChannelSpec(psm=avdtp.AVDTP_PSM))
else:
self.avdtp_server = avdtp_server
+ self.avdtp_server.remove_all_listeners('connection')
self.avdtp_server.on('connection', self._on_l2cap_connection)
def _on_l2cap_connection(self, channel: l2cap.ClassicChannel):
@@ -256,14 +293,7 @@
seid_information: typing.List[av.SeidInformation],
service_capabilities: typing.List[av.ServiceCapability],
timeout: float = 10.0):
- avdtp_future = asyncio.get_running_loop().create_future()
-
- def on_avdtp_connection():
- logger.info(f"AVDTP Opened")
- nonlocal avdtp_future
- avdtp_future.set_result(None)
-
- self.on('connection', on_avdtp_connection)
+ await self.wait_signaling_channel_connected()
expected_configuration: typing.List[av.ServiceCapability] = []
for capability in service_capabilities:
@@ -277,10 +307,6 @@
await self.accept_get_all_capabilities(service_capabilities)
await self.accept_set_configuration(expected_configuration)
await self.accept_open()
- try:
- await asyncio.wait_for(avdtp_future, timeout=timeout)
- except TimeoutError:
- raise TimeoutError(f"TimeoutError while waiting for AVDTP stream to open") from None
async def initiate_delay_report(self, delay_ms: int = 100, timeout: float = 3.0):
delay_one_tenth = delay_ms * 10
diff --git a/android/pandora/test/a2dp_test.py b/android/pandora/test/a2dp_test.py
index f687d3f..e26a6ed 100644
--- a/android/pandora/test/a2dp_test.py
+++ b/android/pandora/test/a2dp_test.py
@@ -943,6 +943,7 @@
DelayReportingCapability()
]
+ await channel.wait_signaling_channel_connected()
await channel.accept_discover(seid_information)
await channel.accept_get_all_capabilities(acceptor_service_capabilities)
await channel.accept_set_configuration(expected_configuration=[
@@ -1015,6 +1016,7 @@
DelayReportingCapability()
]
+ await channel.wait_signaling_channel_connected()
await channel.accept_discover(seid_information)
await channel.accept_get_all_capabilities(acceptor_service_capabilities)
await channel.accept_set_configuration(expected_configuration=[
@@ -1224,6 +1226,7 @@
media_codec_specific_information_elements=ANY)
]
+ await channel.wait_signaling_channel_connected()
await channel.accept_discover(seid_information)
await channel.accept_get_all_capabilities(acceptor_service_capabilities_sbc)
await channel.accept_get_all_capabilities(acceptor_service_capabilities_aac)