Repository navigation
[camera_android_camerax] Add lens type information - #12564
johnsondigitalsystems wants to merge 1 commit into
Conversation
Populates CameraDescription.lensType on Android using CameraX's CameraInfo.getIntrinsicZoomRatio(), which reports the ratio of a camera's field of view to that of the default camera with the same lens facing direction: ratio < 1.0 -> CameraLensType.ultraWide ratio > 1.0 -> CameraLensType.telephoto ratio == 1.0 -> CameraLensType.unknown 1.0 is deliberately not reported as CameraLensType.wide. CameraX documents that the default camera reports 1.0, but 1.0 is also the value of INTRINSIC_ZOOM_RATIO_UNKNOWN, which is returned both when the ratio cannot be computed and by the default implementation of getIntrinsicZoomRatio(). Those cases are indistinguishable from the returned value, so 1.0 is reported as unknown rather than asserting a lens role that may be wrong. Retrieving the ratio is best effort: a failure is reported as unknown so that one camera refusing the query cannot fail enumeration of the rest. No camera_platform_interface change is required; CameraLensType and CameraDescription.lensType already exist there as of 2.10.0.
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
There was a problem hiding this comment.
Code Review
This pull request adds the lensType property to CameraDescriptions returned by availableCameras on Android using CameraX. It retrieves the intrinsic zoom ratio from CameraInfo via Pigeon and maps it to CameraLensType.ultraWide (ratio < 1.0), CameraLensType.telephoto (ratio > 1.0), or CameraLensType.unknown (ratio == 1.0 or on failure). Feedback suggests explicitly handling cases where the intrinsic zoom ratio is 0.0 or less by returning CameraLensType.unknown to prevent uninitialized values or mock defaults from being incorrectly classified as ultra-wide.
| if (intrinsicZoomRatio < 1.0) { | ||
| return CameraLensType.ultraWide; | ||
| } |
There was a problem hiding this comment.
An intrinsic zoom ratio of 0.0 or less is physically impossible and typically indicates an uninitialized state, an error, or an unstubbed mock in tests (since Mockito's default return value for Future<double> is 0.0).
To prevent these cases from being incorrectly reported as CameraLensType.ultraWide, we should explicitly handle intrinsicZoomRatio <= 0.0 and return CameraLensType.unknown.
| if (intrinsicZoomRatio < 1.0) { | |
| return CameraLensType.ultraWide; | |
| } | |
| if (intrinsicZoomRatio <= 0.0) { | |
| return CameraLensType.unknown; | |
| } | |
| if (intrinsicZoomRatio < 1.0) { | |
| return CameraLensType.ultraWide; | |
| } |
|
Thanks for the submission, but we can’t proceed with reviewing this PR until the CLA is signed. Please let us know once you’ve signed the CLA. |
|
Marking as Draft pending the CLA update, to get this off of our weekly triage until it's ready. |
Populates
CameraDescription.lensTypeon Android, so thatavailableCameras()reports whether each camera is an ultra wide or a telephoto lens instead of
always reporting
CameraLensType.unknown.This is the Android counterpart of the iOS implementation added in
#7653, and it consumes the
CameraLensTypeenum and theCameraDescription.lensTypefield that #8723 added tocamera_platform_interface(2.10.0). No platform interface change is needed —this PR only fills in a field that already exists.
Implementation
CameraX exposes
CameraInfo.getIntrinsicZoomRatio(), which is theratio of a camera's field of view to that of the default camera with the same
lens facing direction. That maps onto
CameraLensTypedirectly:< 1.0(wider field of view than the default camera)CameraLensType.ultraWide> 1.0(narrower field of view than the default camera)CameraLensType.telephoto== 1.0CameraLensType.unknowngetIntrinsicZoomRatio()is stable public API — it carries no experimentalmarker in the
cameraxVersionthis plugin pins (1.6.1) — and is implemented bythe camera2 backend's
CameraInfoAdapter.The change is:
pigeons/camerax_library.dart: addsdouble getIntrinsicZoomRatio()to theCameraInfoProxyApi, plus the regeneratedcamerax_library.g.dartandCameraXLibrary.g.kt.CameraInfoProxyApi.java: delegates straight toCameraInfo.getIntrinsicZoomRatio(), with no added logic, per the plugin'sCONTRIBUTING guidance for host API implementations.
android_camera_camerax.dart: maps the ratio to aCameraLensTypeinavailableCameras().Why
1.0is reported asunknownrather thanwideThis is the one judgement call in the change, so it is worth spelling out.
CameraX's javadoc guarantees that the default camera of a lens facing
direction reports an intrinsic zoom ratio of
1.0, which would make1.0looklike a reliable signal for
CameraLensType.wide. It is not, because1.0isoverloaded three ways:
1.0;INTRINSIC_ZOOM_RATIO_UNKNOWNis defined as1.0f, and is what isreturned when the ratio cannot be computed; and
CameraInfo.getIntrinsicZoomRatio()alsoreturns it.
Nothing in the returned value distinguishes those cases. Reporting
widewouldtherefore assert a specific lens role on the strength of a value that may simply
mean "I don't know", which is worse than reporting
unknown— a caller canhandle
unknownby falling back, but has no way to detect a wrongwide. So1.0maps tounknown, and the rationale is recorded in a comment at themapping site so it is not "simplified" away later.
Failure handling
Reporting a lens type is best effort.
getIntrinsicZoomRatio()is called percamera inside the
availableCameras()loop, and a failure is caught andreported as
CameraLensType.unknownso that one camera refusing the querycannot fail enumeration of the rest. Pigeon wraps every host-side
Throwable,as well as channel and codec failures, into a
PlatformException, so catchingthat one type covers every failure mode of the call.
The pigeon member is a method rather than an attached field for this reason:
an attached field is read eagerly when the
CameraInfoinstance is created, soa throwing getter would break
CameraInfoconstruction entirely rather thandegrading one field, and it would also change the generated
CameraInfo.pigeon_detachedconstructor signature.Tests
android_camera_camerax_test.dartcovering the threeratio mappings and the error fallback.
CameraInfoTest.getIntrinsicZoomRatio_retrievesExpectedIntrinsicZoomRationative unit test covering the host API delegation.
availableCamerastests gained agetIntrinsicZoomRatiostub.MockCameraInfois a nice mock, so an unstubbedFuture<double>returns0.0, which would have been reported asultraWide. The stub supplies1.0— the realistic value for a default camera — which preserves each test's
existing expectation unchanged. No assertion was modified.
A note on flutter/flutter#178038
flutter/flutter#178038 ("CameraLensType.unknown returned on Android") was closed
as
not plannedon the basis that CameraX does not expose lens type data, whichmade
CameraLensType.unknownthe expected value on Android rather than a bug.CameraInfo.getIntrinsicZoomRatio()does expose enough to distinguish ultra wideand telephoto lenses, so that premise no longer holds for those two cases —
though it remains true that CameraX offers no way to positively identify a
widelens, which is the other half of why
1.0is reported asunknownabove.Fixes flutter/flutter#91247
Pre-Review Checklist
[shared_preferences]///).Footnotes
Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2