@@ -38,6 +38,8 @@ void audioReceivedOnSink() throws Exception {
3838 CountDownLatch connectedLatch = new CountDownLatch (1 );
3939 CountDownLatch sinkAddedLatch = new CountDownLatch (1 );
4040 CountDownLatch sinkFramesLatch = new CountDownLatch (10 );
41+ CountDownLatch senderClosedLatch = new CountDownLatch (1 );
42+ CountDownLatch receiverClosedLatch = new CountDownLatch (1 );
4143
4244 final AtomicReference <RTCPeerConnection > senderPcRef = new AtomicReference <>();
4345 final AtomicReference <RTCPeerConnection > receiverPcRef = new AtomicReference <>();
@@ -46,7 +48,7 @@ void audioReceivedOnSink() throws Exception {
4648 PeerConnectionObserver receiverObserver = new PeerConnectionObserver () {
4749 @ Override
4850 public void onIceCandidate (RTCIceCandidate candidate ) {
49- // Forward to sender
51+ // Forward to sender.
5052 RTCPeerConnection spc = senderPcRef .get ();
5153 if (spc != null ) {
5254 spc .addIceCandidate (candidate );
@@ -58,6 +60,9 @@ public void onConnectionChange(RTCPeerConnectionState state) {
5860 if (state == RTCPeerConnectionState .CONNECTED ) {
5961 connectedLatch .countDown ();
6062 }
63+ else if (state == RTCPeerConnectionState .CLOSED ) {
64+ receiverClosedLatch .countDown ();
65+ }
6166 }
6267
6368 @ Override
@@ -77,11 +82,21 @@ public void onTrack(RTCRtpTransceiver transceiver) {
7782 }
7883 };
7984
80- // Sender observer: forward ICE to receiver.
81- PeerConnectionObserver senderObserver = candidate -> {
82- RTCPeerConnection rpc = receiverPcRef .get ();
83- if (rpc != null ) {
84- rpc .addIceCandidate (candidate );
85+ // Sender observer: forward ICE to receiver, and listen for CLOSED.
86+ PeerConnectionObserver senderObserver = new PeerConnectionObserver () {
87+ @ Override
88+ public void onIceCandidate (RTCIceCandidate candidate ) {
89+ RTCPeerConnection rpc = receiverPcRef .get ();
90+ if (rpc != null ) {
91+ rpc .addIceCandidate (candidate );
92+ }
93+ }
94+
95+ @ Override
96+ public void onConnectionChange (RTCPeerConnectionState state ) {
97+ if (state == RTCPeerConnectionState .CLOSED ) {
98+ senderClosedLatch .countDown ();
99+ }
85100 }
86101 };
87102
@@ -148,7 +163,7 @@ public void onTrack(RTCRtpTransceiver transceiver) {
148163 }
149164
150165 // Validate that we received audio frames on the remote track sink.
151- assertTrue (sinkFramesLatch .await (1 , TimeUnit .SECONDS ),
166+ assertTrue (sinkFramesLatch .await (3 , TimeUnit .SECONDS ),
152167 "No audio frames received on remote AudioTrack sink" );
153168
154169 receiverAdm .stopPlayout ();
@@ -157,6 +172,13 @@ public void onTrack(RTCRtpTransceiver transceiver) {
157172 // Cleanup.
158173 senderPc .close ();
159174 receiverPc .close ();
175+
176+ // Wait for CLOSED state notifications to avoid races in native teardown.
177+ assertTrue (senderClosedLatch .await (5 , TimeUnit .SECONDS ),
178+ "Sender PC did not reach CLOSED state in time" );
179+ assertTrue (receiverClosedLatch .await (5 , TimeUnit .SECONDS ),
180+ "Receiver PC did not reach CLOSED state in time" );
181+
160182// senderTrack.dispose();
161183// receiverTrack.dispose();
162184 customSource .dispose ();
0 commit comments