Skip to content

[camera_android_camerax] Prefer higher resolution for max preset - #11956

Merged
auto-submit[bot] merged 4 commits into
flutter:mainfrom
brickit-app:fix-camerax-max-high-resolution
Jul 30, 2026
Merged

[camera_android_camerax] Prefer higher resolution for max preset#11956
auto-submit[bot] merged 4 commits into
flutter:mainfrom
brickit-app:fix-camerax-max-high-resolution

Conversation

@kalyujniy

@kalyujniykalyujniy commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Updates camera_android_camerax so ResolutionPreset.max can select Camera2 high-resolution JPEG still capture sizes on Android. For ResolutionPreset.max, ImageCapture now uses ResolutionSelector.PREFER_HIGHER_RESOLUTION_OVER_CAPTURE_RATE; preview and image analysis keep the existing selector without high-resolution mode.

Fixesflutter/flutter#188310

Problem

On some Android devices, Camera2 exposes the largest 4:3 still resolution only through getHighResolutionOutputSizes(ImageFormat.JPEG). The CameraX backend used ResolutionStrategy.HIGHEST_AVAILABLE_STRATEGY without ResolutionSelector.PREFER_HIGHER_RESOLUTION_OVER_CAPTURE_RATE, so CameraX could pick the largest regular JPEG size instead.

Observed

  • Camera2 regular JPEG max: 3264x2448
  • Camera2 high-resolution JPEG: 4624x3468
  • Flutter takePicture(): 2448x3264

After fix

  • CameraX ImageCapture: 4624x3468
  • Flutter takePicture(): 3468x4624

Risk / tradeoff

High-resolution still capture can be slower and use more memory. Limited to ResolutionPreset.max and ImageCapture only.

Note

Generated Pigeon files (camerax_library.g.dart, CameraXLibrary.g.kt) include formatting churn from local pigeon regeneration; functional changes are limited to ResolutionSelector allowed resolution mode and max-preset ImageCapture selector behavior.

Pre-Review Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools.
  • I read the [Tree Hygiene] page, which explains my responsibilities.
  • I read and followed the [relevant style guides] and ran [the auto-formatter].
  • I signed the [CLA].
  • The title of the PR starts with the name of the package surrounded by square brackets, e.g. [shared_preferences]
  • I [linked to at least one issue that this PR fixes] in the description above.
  • I followed [the version and CHANGELOG instructions], using [semantic versioning] and the [repository CHANGELOG style], or I have commented below to indicate which documented exception this PR falls under[^1].
  • I updated/added any relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or I have commented below to indicate which [test exemption] this PR falls under[^1].
  • All existing and new tests are passing.

Test plan

  • flutter test test/android_camera_camerax_test.dart
  • dart run script/tool/bin/flutter_plugin_tools.dart format --packages camera_android_camerax --no-java --no-kotlin --no-clang-format --no-swift
  • dart run script/tool/bin/flutter_plugin_tools.dart analyze --packages camera_android_camerax
  • dart run script/tool/bin/flutter_plugin_tools.dart dart-test --packages camera_android_camerax
  • Java: ResolutionSelectorTest
  • Android native tests (native-test --android) — not run locally (no JRE); left to CI

@google-cla

Copy link
Copy Markdown

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.

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request updates ResolutionPreset.max to support CameraX high-resolution still capture sizes on Android by introducing an allowedResolutionMode configuration to ResolutionSelector. It adds a separate _imageCaptureResolutionSelector for still image capture, allowing the camera to prefer higher resolution over capture rate. The review feedback suggests passing the preset resolution selector as an argument to _getImageCaptureResolutionSelectorFromPreset to eliminate temporal coupling and preserve existing configuration properties.

Comment threadpackages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart Outdated
Comment threadpackages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart Outdated

@camsim99camsim99 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you so much for this change! Without ResolutionSelector.PREFER_HIGHER_RESOLUTION_OVER_CAPTURE_RATE, the plugin was not truly using the highest available resolution.

With that being said, I think this fix should expand beyond ImageCapture. That is, I think all camera use cases should prefer a higher resolution over the capture rate if ResolutionPreset.max is specified. That way, we give developers access to the true highest resolution across the board. Is there some specific reason you think it should only apply to ImageCapture?

///
/// See
/// https://developer.android.com/reference/kotlin/androidx/camera/core/resolutionselector/ResolutionSelector#PREFER_CAPTURE_RATE_OVER_HIGHER_RESOLUTION().
enum ResolutionSelectorAllowedResolutionMode {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would prefer if these were a class of Ints like Surface to better match the actual Android API for clarity.

/// Allowed resolution mode for [ResolutionSelector].
///
/// See
/// https://developer.android.com/reference/kotlin/androidx/camera/core/resolutionselector/ResolutionSelector#PREFER_CAPTURE_RATE_OVER_HIGHER_RESOLUTION().

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: put links in the dart doc for each mode individually

/// For [ResolutionPreset.max], this may differ from [_presetResolutionSelector]
/// to allow CameraX high-resolution still capture sizes without affecting
/// preview or image analysis resolution selection.
ResolutionSelector? _imageCaptureResolutionSelector;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

See my overall review comment. If you agree, this can just be _presetResolutionSelector when ResolutionPreset.max is specified.

public ResolutionSelector pigeon_defaultConstructor(
@Nullable ResolutionFilter resolutionFilter,
@Nullable ResolutionStrategy resolutionStrategy,
@Nullable ResolutionSelectorAllowedResolutionMode allowedResolutionMode,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

See my comment below about this just be an Integer instead of creating a new class.

@kalyujniy

Copy link
Copy Markdown
ContributorAuthor

Thank you so much for this change! Without ResolutionSelector.PREFER_HIGHER_RESOLUTION_OVER_CAPTURE_RATE, the plugin was not truly using the highest available resolution.

With that being said, I think this fix should expand beyond ImageCapture. That is, I think all camera use cases should prefer a higher resolution over the capture rate if ResolutionPreset.max is specified. That way, we give developers access to the true highest resolution across the board. Is there some specific reason you think it should only apply to ImageCapture?

Good point. I initially scoped this to ImageCapture because the original issue was specific to still capture, but I agree that ResolutionPreset.max should consistently prefer higher resolution for all ResolutionSelector-backed use cases.

I updated the shared ResolutionPreset.maxResolutionSelector so Preview, ImageCapture, and ImageAnalysis all use PREFER_HIGHER_RESOLUTION_OVER_CAPTURE_RATE. VideoCapture still uses QualitySelector, so this setting does not apply there directly.

I also replaced the Pigeon enum with nullable int plumbing and Dart int constants with per-mode Android API links, matching the Surface-style wrapper.

I manually verified the updated behavior on a real Android device. With ResolutionPreset.max, CameraX now selects JPEG 4624x3468, and takePicture returns 3468x4624; before this change it selected JPEG 3264x2448 and returned 2448x3264.

@kalyujniy
kalyujniy requested a review from camsim99June 29, 2026 21:30

@camsim99camsim99 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This LGTM! Thanks for the explanation and the quick changes :) let's get a second reviewer

@camsim99
camsim99 requested review from a team, mboetger and reidbaker and removed request for a team and mboetgerJune 30, 2026 22:40
@camsim99camsim99 added the CICD Run CI/CD label Jun 30, 2026
@flutter-dashboard

Copy link
Copy Markdown

This pull request is not mergeable in its current state, likely because of a merge conflict. Pre-submit CI jobs were not triggered. Pushing a new commit to this branch that resolves the issue will result in pre-submit jobs being scheduled.

@camsim99

Copy link
Copy Markdown
Contributor

@kalyujniy Can you take a look at the merge conflicts?

@kalyujniy
kalyujniyforce-pushed the fix-camerax-max-high-resolution branch from b7392ab to f1e3b7cCompareJuly 22, 2026 05:16
@flutter-dashboardflutter-dashboardBot removed the CICD Run CI/CD label Jul 22, 2026
@kalyujniy

kalyujniy commented Jul 22, 2026

Copy link
Copy Markdown
ContributorAuthor

LGTM but the description is outdated now that the scope has expanded to the non-still use cases, can you update?

Done, thanks! I updated the changelog and PR description wording to reflect the expanded scope.

This PR updates the CameraX ResolutionSelector used for ResolutionPreset.max to prefer higher resolution over capture rate. This applies to CameraX use cases backed by ResolutionSelector, including Preview, ImageCapture, and ImageAnalysis.

VideoCapture continues to use QualitySelector, so this setting does not apply there directly.

@camsim99camsim99 added CICD Run CI/CD autosubmit Merge PR when tree becomes green via auto submit App labels Jul 22, 2026
@auto-submit

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/packages/11956, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label.

@auto-submitauto-submitBot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jul 22, 2026
@flutter-dashboardflutter-dashboardBot removed the CICD Run CI/CD label Jul 23, 2026
@kalyujniy
kalyujniyforce-pushed the fix-camerax-max-high-resolution branch from bde2ade to 7e51b76CompareJuly 24, 2026 07:34
@kalyujniy
kalyujniy requested a review from camsim99July 24, 2026 16:05
@kalyujniy

Copy link
Copy Markdown
ContributorAuthor

@camsim99 I noticed autosubmit was removed due to a Dashboard Checks failure. I fixed the generated-file formatting issue that caused Linux repo_checks (format / publishability) to fail, and verified format and publish-check locally.

@gmackallgmackall added the CICD Run CI/CD label Jul 24, 2026
@flutter-dashboardflutter-dashboardBot removed the CICD Run CI/CD label Jul 26, 2026
@camsim99camsim99 added autosubmit Merge PR when tree becomes green via auto submit App CICD Run CI/CD labels Jul 27, 2026
@auto-submitauto-submitBot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jul 27, 2026
@auto-submit

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/packages/11956, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label.

@camsim99

Copy link
Copy Markdown
Contributor

This is currently blocked by the flutter/flutter tree I believe (or at least it's the same failure https://ci.chromium.org/ui/p/flutter/builders/prod/Linux%20plugin_test_android_variants/4862/overview

@kalyujniykalyujniy changed the title [camera_android_camerax] Allow high-resolution still captures for max preset[camera_android_camerax] Prefer higher resolution for max presetJul 30, 2026
@kalyujniy

Copy link
Copy Markdown
ContributorAuthor

This is currently blocked by the flutter/flutter tree I believe (or at least it's the same failure https://ci.chromium.org/ui/p/flutter/builders/prod/Linux%20plugin_test_android_variants/4862/overview

It looks like the flutter/flutter tree issue has been resolved and all checks are green now. The PR is approved and mergeable. Could you please re-apply the autosubmit label when convenient?

@camsim99

Copy link
Copy Markdown
Contributor

@kalyujniy Ah sorry for the delay! Thanks for flagging :)

@camsim99camsim99 added the autosubmit Merge PR when tree becomes green via auto submit App label Jul 30, 2026
@auto-submit
auto-submitBot merged commit 43dcfe5 into flutter:mainJul 30, 2026
14 checks passed
pullBot pushed a commit to ScorpiusDraconis83/flutter that referenced this pull request Jul 31, 2026
…r#190351)
flutter/packages@7d17fc8...5351d8c
2026-07-30 katelovett@google.com [material_ui, cupertino_ui] Add
migration bridge utilities (flutter/packages#12314)
2026-07-30 269567208+reidbaker-agent@users.noreply.github.com Enforce
scoped validation tools in AGENTS.md with file-based trap evals
(flutter/packages#12297)
2026-07-30 engine-flutter-autoroll@skia.org Manual roll Flutter from
c83f80b to 2a230d1 (6 revisions) (flutter/packages#12325)
2026-07-30 engine-flutter-autoroll@skia.org Manual roll Flutter from
0f02463 to c83f80b (7 revisions) (flutter/packages#12318)
2026-07-30 kirill.webmail@yandex.com [camera_android_camerax] Prefer
higher resolution for max preset (flutter/packages#11956)
If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC flutter-ecosystem@google.com on the revert to ensure that a
human
is aware of the problem.
To file a bug in Flutter:
https://github.com/flutter/flutter/issues/new/choose
To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622
Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmitMerge PR when tree becomes green via auto submit AppCICDRun CI/CDp: cameraplatform-androidtriage-androidShould be looked at in Android triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[camera_android_camerax] ResolutionPreset.max does not select Camera2 high-resolution JPEG still capture sizes

3 participants

@kalyujniy@camsim99@gmackall