MS-1494 Unified camera frame provider - #1766
Conversation
There was a problem hiding this comment.
Pull request overview
Introduces a new :infra:camera module intended to centralize CameraX initialization/capture and expose a unified stream of camera frames (with optional high-resolution capture mode), plus basic post-processing utilities (target crop + QR decode). This fits the infra layer by providing reusable camera and image-processing building blocks for upcoming feature-module changes.
Changes:
- Added
:infra:cameramodule withCameraFrameProvider, frame emission controller, focus helper, bitmap normalization, cropping, and QR detection use cases. - Added unit tests for bitmap normalization, target cropping, and frame emission gating.
- Wired the new module into Gradle settings, CI path filters/matrix, and logging crash-report tags (
CrashReportTag.CAMERA).
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| settings.gradle.kts | Includes the new :infra:camera module in the build. |
| infra/logging/src/main/java/com/simprints/infra/logging/LoggingConstants.kt | Adds CAMERA crash-report tag for camera-related logging. |
| infra/camera/build.gradle.kts | Defines the new infra camera module and its dependencies (CameraX + MLKit barcode). |
| infra/camera/src/main/AndroidManifest.xml | Adds minimal manifest for the new Android library module. |
| infra/camera/.gitignore | Ignores the module’s build outputs. |
| infra/camera/src/main/java/com/simprints/infra/camera/Frame.kt | Introduces a frame model carrying bitmap + rotation + preview/target bounds. |
| infra/camera/src/main/java/com/simprints/infra/camera/CameraFrameProvider.kt | Implements unified frame emission + high-res capture mode over CameraX. |
| infra/camera/src/main/java/com/simprints/infra/camera/helpers/FrameEmissionHelper.kt | Adds gating logic to pause/resume emission and serialize high-res captures. |
| infra/camera/src/main/java/com/simprints/infra/camera/helpers/CameraFocusHelper.kt | Adds focus-on-tap and autofocus setup utilities for PreviewView. |
| infra/camera/src/main/java/com/simprints/infra/camera/usecase/NormalizeHighResBitmapToPreviewUseCase.kt | Normalizes high-res captures to match preview aspect ratio and dimensions. |
| infra/camera/src/main/java/com/simprints/infra/camera/postprocess/FrameCropToTargetUseCase.kt | Crops emitted frames to a target rectangle derived from preview overlay bounds. |
| infra/camera/src/main/java/com/simprints/infra/camera/postprocess/DetectQrCodeUseCase.kt | Adds MLKit-based QR decoding from a frame bitmap with error logging. |
| infra/camera/src/test/java/com/simprints/infra/camera/usecase/NormalizeBitmapToPreviewUseCaseTest.kt | Adds tests for high-res normalization (naming currently mismatched). |
| infra/camera/src/test/java/com/simprints/infra/camera/postprocess/FrameCropToTargetUseCaseTest.kt | Adds tests validating cropping behavior across preview/image size scenarios. |
| infra/camera/src/test/java/com/simprints/infra/camera/helpers/FrameEmissionControllerTest.kt | Adds tests for frame emission gating (file/class naming mismatch). |
| .github/workflows/pr-checks.yml | Ensures infra/camera/** participates in CI change detection and unit test matrix. |
Suppressed comments (1)
infra/camera/src/main/java/com/simprints/infra/camera/CameraFrameProvider.kt:190
emitFrame()callstryEmitonframes, butframesis exposed asFlow(read-only) and doesn’t providetryEmit. Emit on the backingMutableSharedFlowinstead.
frames.tryEmit(Frame(bitmap = bitmap, rotation = rotation, previewBounds = previewRect, targetBounds = targetRect))
92bf21e to
f8add24
Compare
| class FrameCropToTargetUseCase @Inject constructor() { | ||
| operator fun invoke(frame: Frame): Bitmap { | ||
| if (frame.targetBounds.isEmpty) { | ||
| return frame.bitmap |
There was a problem hiding this comment.
I'd say we should log something here (exception, even?) - calling the cropping use case without target bounds doesn't seem to make sense, and probably indicates that some logic is wrong upstream
There was a problem hiding this comment.
We could, but I am not sure how helpful it would be. This prevent a crash if something went extremely wrong. We are likely to catch the such issues while debugging preview than while looking at logs.
f868ae5 to
824ca4b
Compare
824ca4b to
dca35ac
Compare
|


JIRA ticket
Will be released in: 2026.3.0
Notable changes
While this might seem as a complicated setup in isolation, it is the minimal amount of functionality that covers all existing use cases in our modules while providing a solid base for the test image injection. It will become clearer when more PRs are added to the stack.
Testing guidance
Additional work checklist