Skip to content

fix(android): type physical cameras by field of view - #4240

Open
Rubenkl wants to merge 1 commit into
margelo:mainfrom
Rubenkl:fix/android-physical-device-type
Open

Rubenkl wants to merge 1 commit into
margelo:mainfrom
Rubenkl:fix/android-physical-device-type

Conversation

@Rubenkl

@Rubenkl Rubenkl commented Nov 7, 2026

Copy link
Copy Markdown

What

On Android, every entry in CameraDevice.physicalDevices reports type: 'unknown'. CameraInfo+deviceType.kt returns early for a PhysicalCameraInfoAdapter, with a TODO that says the adapter throws on intrinsicZoomRatio.

This also affects the physicalDevices filter of useCameraDevice(...) and getCameraDevice(...). A logical camera loses a point for every 'unknown' lens, so a standalone camera at the same position always wins. On the Samsung layout from #4038, the triple filter from the docs returns the standalone ultra-wide instead of the triple camera.

Fix

A physical camera is now typed by its own diagonal field of view, like VisionCamera 4 did in CameraDeviceDetails.getDeviceTypes(). It uses the shortest LENS_INFO_AVAILABLE_FOCAL_LENGTHS entry and SENSOR_INFO_PHYSICAL_SIZE from the physical camera's CameraCharacteristics, which HybridPhysicalCameraDevice already reads for focalLength. Above 94 degrees is ultra-wide-angle, 60 to 94 is wide-angle, and below 60 is telephoto. Without those characteristics it still returns unknown. Standalone and logical cameras are unchanged.

I did not switch to intrinsicZoomRatio. In CameraX 1.7.0-alpha03 it no longer throws on a physical camera, so the TODO is outdated. It divides the horizontal view angle of the default camera at that position by this camera's, both truncated to whole degrees, and the result is not rounded. With the strict < 1f check, a main lens one degree wider than the default camera would come out as ultra-wide-angle.

Test

visioncamera.devices.harness.ts gets one case: each physical device of a virtual device must report a PhysicalDeviceType, which are the types the physicalDevices filter can match. It skips when there is no virtual device.

I ran it on an Android 16 (API 36) arm64 emulator started with -camera-back emulated -camera-front emulated. Its front camera 1 is a logical camera of physical cameras 4 (4.38 mm on a 5.64 x 4.23 mm sensor, about 78 degrees) and 5 (5.84 mm on a 4.66 x 3.50 mm sensor, about 53 degrees).

  • On main: fails with expected [ 'ultra-wide-angle', …(7) ] to include 'unknown'.
  • With this change: passes. Camera 4 reports wide-angle and camera 5 reports telephoto.

The existing "does not expose unknown fallback values" test checks for the same 'unknown'. On this emulator it already fails earlier, on a top-level device's supportedPixelFormats, so it never reaches the physical devices. That failure is the same on main and on this branch. The rest of the Harness suite also fails the same way on both builds on this emulator, apart from the flaky "applies the initial torchMode prop" test in the camera-view suite.

Also ran:

  • bun camera typecheck
  • bun run build and bunx tsc --noEmit -p apps/simple-camera/tsconfig.json
  • bun lint-js
  • bun lint-kotlin (ktlint 1.8.0, no changes)
  • ./gradlew assembleDebug -PreactNativeArchitectures=arm64-v8a in apps/simple-camera/android

Notes

  • Standalone cameras still use intrinsicZoomRatio. I left that path alone to keep this change small.
  • I have not run this on a physical phone, so the Device Farm run is the first real-device check.

Prepared with an AI coding assistant. I reviewed the change, and the emulator run was done on my machine.

Physical cameras inside a logical multi-camera always reported
`type: 'unknown'`. Type them by the diagonal field of view of their
shortest focal length, computed from their own
LENS_INFO_AVAILABLE_FOCAL_LENGTHS and SENSOR_INFO_PHYSICAL_SIZE, with
the VisionCamera 4 thresholds: above 94 degrees ultra-wide-angle,
60 to 94 wide-angle, below 60 telephoto. If those characteristics are
missing, the type stays `unknown`.

Adds a Harness test that checks the type of each physical device of a
virtual device, and skips when there is none.
@vercel

vercel Bot commented Nov 7, 2026

Copy link
Copy Markdown

@Rubenkl is attempting to deploy a commit to the Margelo Team on Vercel.

A member of the Team first needs to authorize it.

@Rubenkl

Rubenkl commented Nov 7, 2026

Copy link
Copy Markdown
Author

@mrousavy, a small Android fix for physicalDevices. Today every lens inside a multi-camera reports 'unknown' on Android, so useCameraDevice(..., { physicalDevices: [...] }) cannot pick a camera by its lenses there. On the Samsung layout from #4038, the triple filter from the docs returns the standalone ultra-wide. With this change the lenses report ultra-wide-angle, wide-angle or telephoto, so the filter works like it does on iOS.

The workflows are waiting for approval because this is my first PR here. Could you approve them so CI can run? Thanks!

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