Repository navigation
Fixed the Android Robot video feed freezing issue in the Flutter Controller. - #551
Conversation
|
Thanks for the fix and device testing. Two concerns:
Please cover both cases in testing. |
|
|
Thanks for addressing both concerns. One remaining edge case: the delayed camera-switch callback can run after |
There was a problem hiding this comment.
🟡 Changes recommended
Preview lifecycle gaps, a signaling race, and incomplete resource disposal leave freezing and reliability issues unresolved.
5 open issues
What changed in this PR
This PR addresses Android robot video freezes by sharing preview frames with WebRTC and refreshing controller connections when video restarts.
Changes:
- Shares CameraX preview frames and manages camera handoffs.
- Reworks call teardown, restart, and signaling handling.
- Serializes Flutter signaling and replaces connections for new offers.
| File | Description |
|---|---|
| controller/flutter/lib/screens/controller.dart | Queues signaling and replaces connections on new offers. |
| android/robot/src/main/java/org/openbot/app/robot/env/WebRtcServer.java | Adds shared-frame streaming and revises call lifecycle handling. |
| android/robot/src/main/java/org/openbot/app/robot/env/PhoneController.java | Restarts video when reusing an open connection. |
| android/robot/src/main/java/org/openbot/app/robot/common/CameraFragment.java | Registers preview ownership and forwards camera frames. |
Review effort: Balanced
| if (peerConnection == null) { | ||
| // Late message after the call closed. Throwing here would end this subscription. | ||
| Log.d(TAG, "Ignoring WebRTC event: no active call"); | ||
| return; |
| try { | ||
| if (cameraProvider != null) { | ||
| cameraProvider.unbindAll(); | ||
| WebRtcServer.setLocalPreviewActive(this, true, this::switchCameraForController); |
| public void onDestroy() { | ||
| super.onDestroy(); | ||
| cameraExecutor.shutdown(); | ||
| WebRtcServer.setLocalPreviewActive(this, false, null); |
| mediaStream = null; | ||
| videoSender = null; | ||
| audioSender = null; | ||
| videoTrackFromCamera = null; | ||
| localAudioTrack = null; |
| // The robot starts a new call with a fresh offer every time it restarts video, so a second | ||
| // offer belongs to a new call: replace the peer connection instead of renegotiating on it. | ||
| if (await _peerConnection?.getRemoteDescription() != null) { | ||
| await _peerConnection?.close(); |
- Handle start/stop and controller signaling on the main thread so they can't race with closeCall(). - Always resume the local preview after an interrupted camera switch. - Release preview ownership if camera binding fails. - Dispose local stream/tracks and the replaced Flutter peer connection.
|
Thanks for the fixes! I pushed a follow-up commit for the remaining review points:
Pausing the feed while the robot app is on a settings screen is expected, so I left that as is. Could you re-test on a device before we merge?
|
Thanks for the follow-up! Re-tested on device with 403b845 on the Android, iOS and web controllers: all 5 scenarios pass. Video works, controller mode off/on resumes video, camera switch works in Free Roam and Logger, reconnecting works, and the preview comes back after a switch followed by an immediate disconnect. Agreed on the settings screen pause. |
…android/robot-connection
thias15
left a comment
There was a problem hiding this comment.
Tested on device by the author; review comments addressed.


Tested for
Also tested switching simultaneously between different fragments with real robot.