Skip to content

Conversation

@david-livefront
Copy link
Collaborator

@david-livefront david-livefront commented Nov 18, 2025

🎟️ Tracking

PM-28408

📔 Objective

This PR updates the way the CameraPreview works in order to fix a flakey test. I was never able to reproduce this issue in a controlled scenario, so this is a 🤞 moment. 😄

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

androidx-biometrics = { group = "androidx.biometric", name = "biometric", version.ref = "androidxBiometrics" }
androidx-browser = { module = "androidx.browser:browser", version.ref = "androidxBrowser" }
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "androidxCamera" }
androidx-camera-compose = { module = "androidx.camera:camera-compose", version.ref = "androidxCamera" }
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds native compose support for the camera, something that did not exist previously.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@claude
Copy link
Contributor

claude bot commented Nov 18, 2025

Claude finished @david-livefront's task —— View job


Code Review Complete

Overall Assessment: APPROVE with minor recommendations

This PR successfully modernizes the camera implementation by migrating from AndroidView with PreviewView to native Compose CameraX (CameraXViewfinder). The changes are architecturally sound and should improve test stability.

Summary of Changes

  1. CameraPreview.kt (ui:60-88): Replaces AndroidView/PreviewView with CameraXViewfinder, simplifying the implementation by ~20 lines and eliminating DisposableEffect/suspendCoroutine complexity
  2. QrCodeAnalyzerImpl.kt (ui:24-57): Renames qrCodeReadisQrCodeInAnalysis and resets the flag in finally block, enabling re-scanning after successful QR decode
  3. Dependency: Adds androidx.camera:camera-compose to support native Compose camera integration

Findings

Finding 1: Comment accuracy issue in QrCodeAnalyzerImpl.kt

Details

The comment at ui/src/main/kotlin/com/bitwarden/ui/platform/feature/qrcodescan/util/QrCodeAnalyzerImpl.kt:22-23 states "ensure that only 1 QR code is analyzed at a time" but this is ambiguous given the behavioral change.

Old behavior: Flag prevented multiple QR scans permanently (one-shot)
New behavior: Flag prevents concurrent processing of the same frame only (allows sequential re-scanning)

The author confirmed this is intentional to allow re-scanning. The comment should clarify this distinction:

/**
 * Prevents concurrent processing of frames. The flag resets after each frame
 * completes processing, allowing multiple QR codes to be scanned sequentially.
 */
private var isQrCodeInAnalysis: Boolean = false

This makes the behavioral intent clearer for future maintainers.


Finding 2: Potential test synchronization consideration

Details

The new implementation introduces async initialization via LaunchedEffect that:

  1. Obtains camera provider asynchronously
  2. Sets surfaceRequests.value = request
  3. Triggers recomposition to render CameraXViewfinder

If the flaky test persists, consider whether tests need to wait for surfaceRequest != null state or use advanceUntilIdle() for coroutine-based assertions. The migration itself is architecturally correct.

Reference: ui/src/main/kotlin/com/bitwarden/ui/platform/components/camera/CameraPreview.kt:44-67


Positive Observations

  • Error handling preserved (try-catch at :57-59, camera availability check at :48)
  • Proper use of remember for stable references (:41, :73, :83)
  • Test coverage maintained (no test deletions in diff)
  • Follows MVVM/Compose architecture patterns per docs/ARCHITECTURE.md
  • Code reduction (~20 lines) improves maintainability

),
)

qrCodeRead = true
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This used to only allow 1 QR code to be read but now we allow other to be processed once the code has been processed

@github-actions
Copy link
Contributor

github-actions bot commented Nov 18, 2025

Logo
Checkmarx One – Scan Summary & Details7705fede-f68d-415d-b7c2-365cd42ee036

Great job! No new security vulnerabilities introduced in this pull request

@david-livefront david-livefront force-pushed the fix-flakey-camera-test branch 2 times, most recently from 58440a2 to 1f89dc1 Compare November 18, 2025 20:12
@codecov
Copy link

codecov bot commented Nov 18, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.24%. Comparing base (621f97d) to head (0626947).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6178   +/-   ##
=======================================
  Coverage   85.24%   85.24%           
=======================================
  Files         724      724           
  Lines       52899    52901    +2     
  Branches     7687     7687           
=======================================
+ Hits        45092    45094    +2     
  Misses       5126     5126           
  Partials     2681     2681           

☔ View full report in Codecov by Sentry.
📢 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.

Copy link
Contributor

@andrebispo5 andrebispo5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good. Let's see if it fixes the problem 🤞

@david-livefront
Copy link
Collaborator Author

Thanks @andrebispo5

@david-livefront david-livefront added this pull request to the merge queue Nov 19, 2025
Merged via the queue into main with commit 979237b Nov 19, 2025
21 checks passed
@david-livefront david-livefront deleted the fix-flakey-camera-test branch November 19, 2025 16:18
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.

4 participants