fix(replay): isolate Android decor window streams - #754
Closed
dustinbyrne wants to merge 2 commits into
Closed
Conversation
Contributor
posthog-android Compliance ReportDate: 2026-09-02 15:55:53 UTC ✅ All Tests Passed!46/46 tests passed Capture Tests✅ 29/29 tests passed View Details
Feature_Flags Tests✅ 17/17 tests passed View Details
|
Contributor
Author
|
this is not the right fix |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
💡 Motivation and Context
Fixes #752.
$window_idis the document identity used by PostHog's replay pipeline. Snapshot ingestion groups events by it, and the player feeds each group to rrweb as one document timeline. A full snapshot rebuilds that timeline's document and node mirror; later incremental snapshots apply mutations to node IDs from that same document.Android previously fell back to
$window_id = $session_idfor every native window. An Activity and a Dialog in the same recording therefore collapsed into one rrweb timeline. When the Dialog emitted its full snapshot, rrweb replaced the Activity document and node mirror with the Dialog's. After the Dialog closed, subsequent Activity mutations still referenced nodes from the original Activity document, so rrweb could not apply them and the recording became incomplete or appeared frozen. The window ID is therefore not optional metadata: each concurrently represented native document needs a distinct, stable value, while$session_idremains shared across the recording.This change gives each tracked decor view a stable replay window ID and preserves that identity across snapshot-state resets. Snapshot batches and native touches use their owning decor ID. Network and logcat replay events use the foreground native decor at emission time, falling back to the existing session-derived ID when no native decor is eligible. Flutter-owned replay streams retain that fallback, while explicit native bridge snapshots use their decor ID.
💚 How did you test it?
make testmake compilemake checkFormat./gradlew apiCheckA, B, A, Aunder one session.📝 Checklist
If releasing new changes
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Implemented and validated with the Pi coding agent using Gradle, ADB, a local capture server, and the PostHog replay transformer/player. Fresh Pi reviewer agents reviewed the design and implementation. The human directed the investigation and window-identity contract, discussed the implementation throughout, and has been good to me. Reviewer feedback identified and corrected a lifecycle race where synchronous removal during touch dispatch could otherwise restore a stale foreground window.