Skip to content

refactor(llc): move app lifecycle handling into AppLifecycleController - #1439

Draft
renefloor wants to merge 2 commits into
feat/flu-863-call-ringing-controllerfrom
feat/flu-858-app-lifecycle-controller
Draft

renefloor wants to merge 2 commits into
feat/flu-863-call-ringing-controllerfrom
feat/flu-858-app-lifecycle-controller

Conversation

@renefloor

Copy link
Copy Markdown
Contributor

Fixes FLU-858

Part of FLU-859 · 24/26, stacked on #1438

What changed

  • AppLifecycleController (lib/src/lifecycle/, @internal) handles the client's side of the app lifecycle:
    • It writes state.appLifecycleState.
    • It closes the coordinator connection in the background when no call is active, unless keepConnectionsAliveWhenInBackground is set.
    • Its inputs are the client state, the keep-alive option, isConnected, and closeConnection / openConnection callbacks. The callbacks also drop and restore the event subscription.
  • Resume reopens only when needed. It used to call openConnection() and re-add the event subscription on every resume, even when nothing had closed the connection. It now reopens when the controller closed the connection, or when the client reports it is no longer connected: a connection kept alive can still drop in the background.
  • Each call mutes and restores its own media (Rene's decision):
    • Call follows state.appLifecycleState while it is active.
    • LocalMediaController (B1) gains onAppPaused and onAppResumed, with the camera and microphone flags of that one call, and _multitaskingCameraAccessSupported moves in with them.
    • The _mutedCameraByStateChange and _mutedAudioByStateChange maps in StreamVideo are gone.
    • The device.stateChange trace moves with them.
  • Errors are caught per step. One try/catch used to swallow the whole handler, so a failed close or a failed mute skipped everything after it. Now a failed close or reopen is logged and the controller goes on, and each call logs its own mute failures.

Decisions to check

  • A call follows the client state's appLifecycleState, not the raw lifecycle stream. Call already has the client state, and B6's CallHost exposes it. The emitter replays its value when the call starts following it, but the call is not active yet at that point (_init runs before setActiveCall), so that value is never acted on. One test pins it: a call joined while the app is in the background is muted only the next time the app goes there.
  • Calls mute concurrently. Before, the handler awaited one call after another. Now each call reacts to the same state change on its own.
  • The ticket's "interaction with a reconnecting call" is not tested on its own. During a reconnect, a mute goes to the session the call holds at that moment, as any mute does. LocalMediaController has no reconnect-specific path to pin.

Tests

  • New: test/src/lifecycle/app_lifecycle_controller_test.dart (6), on the C2 fixture:
    • closing in the background and reopening on resume;
    • kept open with an active call;
    • kept open with keep-alive;
    • a kept connection that dropped is reopened;
    • the app state is recorded;
    • a close that throws doesn't stop the reopen.
  • New: test/src/call/call_background_mute_test.dart (5):
    • the camera and microphone go off in the background and back on after;
    • only what was turned off comes back on;
    • a call that isn't active is left alone;
    • a call joined in the background;
    • nothing happens once the call is left.
  • Mutation checks: dropping the active-call guard, or the restore flag, fails a test.
  • Fixture: setupMockClientState stubs appLifecycleState.
  • Results:
    • stream_video: 1309 passed;
    • stream_video_push_notification: 67;
    • stream_video_flutter without goldens: 729.

🤖 Generated with Claude Code

renefloor and others added 2 commits October 8, 2026 21:13
The client keeps only the connection keep-alive: it closes the
connection in the background with no active call, and reopens it when
it closed it or the connection dropped. Each active call mutes and
restores its own camera and microphone, so the per-cid mute maps in
StreamVideo are gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Oct 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.52055% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 44.59%. Comparing base (4b7be44) to head (dd8da4e).

Files with missing lines Patch % Lines
...deo/lib/src/call/media/local_media_controller.dart 92.85% 2 Missing ⚠️
packages/stream_video/lib/src/call/call.dart 93.33% 1 Missing ⚠️
...eo/lib/src/lifecycle/app_lifecycle_controller.dart 94.11% 1 Missing ⚠️
Additional details and impacted files
@@                           Coverage Diff                            @@
##           feat/flu-863-call-ringing-controller    #1439      +/-   ##
========================================================================
+ Coverage                                 44.40%   44.59%   +0.19%     
========================================================================
  Files                                       422      423       +1     
  Lines                                     31481    31506      +25     
========================================================================
+ Hits                                      13979    14051      +72     
+ Misses                                    17502    17455      -47     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@renefloor
renefloor added this pull request to stack #1442 October 9, 2026 06:12

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant