[camerax] Wrap classes to implement resolution configuration for image capture, image analysis, and preview (#4523)

Wraps classes to implement resolution configuration for image capture, image analysis, and preview. Also bumps CameraX version to latest and removes the deprecated classes used previously.

No functionality changes. Also thanks to @bparrishMines who did majority of the work here!

Part of https://github.com/flutter/flutter/issues/120462
diff --git a/packages/camera/camera_android_camerax/CHANGELOG.md b/packages/camera/camera_android_camerax/CHANGELOG.md
index ab60e8a..1cddca1 100644
--- a/packages/camera/camera_android_camerax/CHANGELOG.md
+++ b/packages/camera/camera_android_camerax/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 0.5.0+12
+
+* Wraps classes needed to implement resolution configuration for image capture, image analysis, and preview.
+* Removes usages of deprecated APIs for resolution configuration.
+* Bumps CameraX version to 1.3.0-beta01.
+
 ## 0.5.0+11
 
 * Fixes issue with image data not being emitted after relistening to stream returned by `onStreamedFrameAvailable`.
diff --git a/packages/camera/camera_android_camerax/android/build.gradle b/packages/camera/camera_android_camerax/android/build.gradle
index f10f133..5530a3b 100644
--- a/packages/camera/camera_android_camerax/android/build.gradle
+++ b/packages/camera/camera_android_camerax/android/build.gradle
@@ -61,7 +61,7 @@
 
 dependencies {
     // CameraX core library using the camera2 implementation must use same version number.
-    def camerax_version = "1.3.0-alpha05"
+    def camerax_version = "1.3.0-beta01"
     implementation "androidx.camera:camera-core:${camerax_version}"
     implementation "androidx.camera:camera-camera2:${camerax_version}"
     implementation "androidx.camera:camera-lifecycle:${camerax_version}"
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/AspectRatioStrategyHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/AspectRatioStrategyHostApiImpl.java
new file mode 100644
index 0000000..91e0def
--- /dev/null
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/AspectRatioStrategyHostApiImpl.java
@@ -0,0 +1,65 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.camera.core.resolutionselector.AspectRatioStrategy;
+import io.flutter.plugins.camerax.GeneratedCameraXLibrary.AspectRatioStrategyHostApi;
+
+/**
+ * Host API implementation for {@link AspectRatioStrategy}.
+ *
+ * <p>This class handles instantiating and adding native object instances that are attached to a
+ * Dart instance or handle method calls on the associated native class or an instance of the class.
+ */
+public class AspectRatioStrategyHostApiImpl implements AspectRatioStrategyHostApi {
+  private final InstanceManager instanceManager;
+  private final AspectRatioStrategyProxy proxy;
+
+  /** Proxy for constructors and static method of {@link AspectRatioStrategy}. */
+  @VisibleForTesting
+  public static class AspectRatioStrategyProxy {
+    /** Creates an instance of {@link AspectRatioStrategy}. */
+    @NonNull
+    public AspectRatioStrategy create(
+        @NonNull Long preferredAspectRatio, @NonNull Long fallbackRule) {
+      return new AspectRatioStrategy(preferredAspectRatio.intValue(), fallbackRule.intValue());
+    }
+  }
+
+  /**
+   * Constructs an {@link AspectRatioStrategyHostApiImpl}.
+   *
+   * @param instanceManager maintains instances stored to communicate with attached Dart objects
+   */
+  public AspectRatioStrategyHostApiImpl(@NonNull InstanceManager instanceManager) {
+    this(instanceManager, new AspectRatioStrategyProxy());
+  }
+
+  /**
+   * Constructs an {@link AspectRatioStrategyHostApiImpl}.
+   *
+   * @param instanceManager maintains instances stored to communicate with attached Dart objects
+   * @param proxy proxy for constructors and static method of {@link AspectRatioStrategy}
+   */
+  @VisibleForTesting
+  AspectRatioStrategyHostApiImpl(
+      @NonNull InstanceManager instanceManager, @NonNull AspectRatioStrategyProxy proxy) {
+    this.instanceManager = instanceManager;
+    this.proxy = proxy;
+  }
+
+  /**
+   * Creates an {@link AspectRatioStrategy} instance with the preferred aspect ratio and fallback
+   * rule specified.
+   */
+  @Override
+  public void create(
+      @NonNull Long identifier, @NonNull Long preferredAspectRatio, @NonNull Long fallbackRule) {
+    instanceManager.addDartCreatedInstance(
+        proxy.create(preferredAspectRatio, fallbackRule), identifier);
+  }
+}
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java
index dd8ab51..dbae2a4 100644
--- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java
@@ -97,6 +97,12 @@
         binaryMessenger, pendingRecordingHostApiImpl);
     videoCaptureHostApiImpl = new VideoCaptureHostApiImpl(binaryMessenger, instanceManager);
     GeneratedCameraXLibrary.VideoCaptureHostApi.setup(binaryMessenger, videoCaptureHostApiImpl);
+    GeneratedCameraXLibrary.ResolutionSelectorHostApi.setup(
+        binaryMessenger, new ResolutionSelectorHostApiImpl(instanceManager));
+    GeneratedCameraXLibrary.ResolutionStrategyHostApi.setup(
+        binaryMessenger, new ResolutionStrategyHostApiImpl(instanceManager));
+    GeneratedCameraXLibrary.AspectRatioStrategyHostApi.setup(
+        binaryMessenger, new AspectRatioStrategyHostApiImpl(instanceManager));
   }
 
   @Override
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/GeneratedCameraXLibrary.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/GeneratedCameraXLibrary.java
index c6f6279..680ecb8 100644
--- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/GeneratedCameraXLibrary.java
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/GeneratedCameraXLibrary.java
@@ -76,6 +76,23 @@
     }
   }
 
+  /**
+   * The types (T) properly wrapped to be used as a LiveData<T>.
+   *
+   * <p>If you need to add another type to support a type S to use a LiveData<S> in this plugin,
+   * ensure the following is done on the Dart side:
+   *
+   * <p>* In `../lib/src/live_data.dart`, add new cases for S in
+   * `_LiveDataHostApiImpl#getValueFromInstances` to get the current value of type S from a
+   * LiveData<S> instance and in `LiveDataFlutterApiImpl#create` to create the expected type of
+   * LiveData<S> when requested.
+   *
+   * <p>On the native side, ensure the following is done:
+   *
+   * <p>* Update `LiveDataHostApiImpl#getValue` is updated to properly return identifiers for
+   * instances of type S. * Update `ObserverFlutterApiWrapper#onChanged` to properly handle
+   * receiving calls with instances of type S if a LiveData<S> instance is observed.
+   */
   public enum LiveDataSupportedType {
     CAMERA_STATE(0),
     ZOOM_STATE(1);
@@ -1297,8 +1314,6 @@
       switch (type) {
         case (byte) 128:
           return ResolutionInfo.fromList((ArrayList<Object>) readValue(buffer));
-        case (byte) 129:
-          return ResolutionInfo.fromList((ArrayList<Object>) readValue(buffer));
         default:
           return super.readValueOfType(type, buffer);
       }
@@ -1309,9 +1324,6 @@
       if (value instanceof ResolutionInfo) {
         stream.write(128);
         writeValue(stream, ((ResolutionInfo) value).toList());
-      } else if (value instanceof ResolutionInfo) {
-        stream.write(129);
-        writeValue(stream, ((ResolutionInfo) value).toList());
       } else {
         super.writeValue(stream, value);
       }
@@ -1322,9 +1334,7 @@
   public interface PreviewHostApi {
 
     void create(
-        @NonNull Long identifier,
-        @Nullable Long rotation,
-        @Nullable ResolutionInfo targetResolution);
+        @NonNull Long identifier, @Nullable Long rotation, @Nullable Long resolutionSelectorId);
 
     @NonNull
     Long setSurfaceProvider(@NonNull Long identifier);
@@ -1351,12 +1361,14 @@
                 ArrayList<Object> args = (ArrayList<Object>) message;
                 Number identifierArg = (Number) args.get(0);
                 Number rotationArg = (Number) args.get(1);
-                ResolutionInfo targetResolutionArg = (ResolutionInfo) args.get(2);
+                Number resolutionSelectorIdArg = (Number) args.get(2);
                 try {
                   api.create(
                       (identifierArg == null) ? null : identifierArg.longValue(),
                       (rotationArg == null) ? null : rotationArg.longValue(),
-                      targetResolutionArg);
+                      (resolutionSelectorIdArg == null)
+                          ? null
+                          : resolutionSelectorIdArg.longValue());
                   wrapped.add(0, null);
                 } catch (Throwable exception) {
                   ArrayList<Object> wrappedError = wrapError(exception);
@@ -1911,40 +1923,11 @@
           channelReply -> callback.reply(null));
     }
   }
-
-  private static class ImageCaptureHostApiCodec extends StandardMessageCodec {
-    public static final ImageCaptureHostApiCodec INSTANCE = new ImageCaptureHostApiCodec();
-
-    private ImageCaptureHostApiCodec() {}
-
-    @Override
-    protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
-      switch (type) {
-        case (byte) 128:
-          return ResolutionInfo.fromList((ArrayList<Object>) readValue(buffer));
-        default:
-          return super.readValueOfType(type, buffer);
-      }
-    }
-
-    @Override
-    protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
-      if (value instanceof ResolutionInfo) {
-        stream.write(128);
-        writeValue(stream, ((ResolutionInfo) value).toList());
-      } else {
-        super.writeValue(stream, value);
-      }
-    }
-  }
-
   /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
   public interface ImageCaptureHostApi {
 
     void create(
-        @NonNull Long identifier,
-        @Nullable Long flashMode,
-        @Nullable ResolutionInfo targetResolution);
+        @NonNull Long identifier, @Nullable Long flashMode, @Nullable Long resolutionSelectorId);
 
     void setFlashMode(@NonNull Long identifier, @NonNull Long flashMode);
 
@@ -1952,7 +1935,7 @@
 
     /** The codec used by ImageCaptureHostApi. */
     static @NonNull MessageCodec<Object> getCodec() {
-      return ImageCaptureHostApiCodec.INSTANCE;
+      return new StandardMessageCodec();
     }
     /**
      * Sets up an instance of `ImageCaptureHostApi` to handle messages through the
@@ -1970,12 +1953,14 @@
                 ArrayList<Object> args = (ArrayList<Object>) message;
                 Number identifierArg = (Number) args.get(0);
                 Number flashModeArg = (Number) args.get(1);
-                ResolutionInfo targetResolutionArg = (ResolutionInfo) args.get(2);
+                Number resolutionSelectorIdArg = (Number) args.get(2);
                 try {
                   api.create(
                       (identifierArg == null) ? null : identifierArg.longValue(),
                       (flashModeArg == null) ? null : flashModeArg.longValue(),
-                      targetResolutionArg);
+                      (resolutionSelectorIdArg == null)
+                          ? null
+                          : resolutionSelectorIdArg.longValue());
                   wrapped.add(0, null);
                 } catch (Throwable exception) {
                   ArrayList<Object> wrappedError = wrapError(exception);
@@ -2046,6 +2031,182 @@
     }
   }
 
+  private static class ResolutionStrategyHostApiCodec extends StandardMessageCodec {
+    public static final ResolutionStrategyHostApiCodec INSTANCE =
+        new ResolutionStrategyHostApiCodec();
+
+    private ResolutionStrategyHostApiCodec() {}
+
+    @Override
+    protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
+      switch (type) {
+        case (byte) 128:
+          return ResolutionInfo.fromList((ArrayList<Object>) readValue(buffer));
+        default:
+          return super.readValueOfType(type, buffer);
+      }
+    }
+
+    @Override
+    protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
+      if (value instanceof ResolutionInfo) {
+        stream.write(128);
+        writeValue(stream, ((ResolutionInfo) value).toList());
+      } else {
+        super.writeValue(stream, value);
+      }
+    }
+  }
+
+  /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
+  public interface ResolutionStrategyHostApi {
+
+    void create(
+        @NonNull Long identifier, @Nullable ResolutionInfo boundSize, @Nullable Long fallbackRule);
+
+    /** The codec used by ResolutionStrategyHostApi. */
+    static @NonNull MessageCodec<Object> getCodec() {
+      return ResolutionStrategyHostApiCodec.INSTANCE;
+    }
+    /**
+     * Sets up an instance of `ResolutionStrategyHostApi` to handle messages through the
+     * `binaryMessenger`.
+     */
+    static void setup(
+        @NonNull BinaryMessenger binaryMessenger, @Nullable ResolutionStrategyHostApi api) {
+      {
+        BasicMessageChannel<Object> channel =
+            new BasicMessageChannel<>(
+                binaryMessenger, "dev.flutter.pigeon.ResolutionStrategyHostApi.create", getCodec());
+        if (api != null) {
+          channel.setMessageHandler(
+              (message, reply) -> {
+                ArrayList<Object> wrapped = new ArrayList<Object>();
+                ArrayList<Object> args = (ArrayList<Object>) message;
+                Number identifierArg = (Number) args.get(0);
+                ResolutionInfo boundSizeArg = (ResolutionInfo) args.get(1);
+                Number fallbackRuleArg = (Number) args.get(2);
+                try {
+                  api.create(
+                      (identifierArg == null) ? null : identifierArg.longValue(),
+                      boundSizeArg,
+                      (fallbackRuleArg == null) ? null : fallbackRuleArg.longValue());
+                  wrapped.add(0, null);
+                } catch (Throwable exception) {
+                  ArrayList<Object> wrappedError = wrapError(exception);
+                  wrapped = wrappedError;
+                }
+                reply.reply(wrapped);
+              });
+        } else {
+          channel.setMessageHandler(null);
+        }
+      }
+    }
+  }
+  /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
+  public interface ResolutionSelectorHostApi {
+
+    void create(
+        @NonNull Long identifier,
+        @Nullable Long resolutionStrategyIdentifier,
+        @Nullable Long aspectRatioStrategyIdentifier);
+
+    /** The codec used by ResolutionSelectorHostApi. */
+    static @NonNull MessageCodec<Object> getCodec() {
+      return new StandardMessageCodec();
+    }
+    /**
+     * Sets up an instance of `ResolutionSelectorHostApi` to handle messages through the
+     * `binaryMessenger`.
+     */
+    static void setup(
+        @NonNull BinaryMessenger binaryMessenger, @Nullable ResolutionSelectorHostApi api) {
+      {
+        BasicMessageChannel<Object> channel =
+            new BasicMessageChannel<>(
+                binaryMessenger, "dev.flutter.pigeon.ResolutionSelectorHostApi.create", getCodec());
+        if (api != null) {
+          channel.setMessageHandler(
+              (message, reply) -> {
+                ArrayList<Object> wrapped = new ArrayList<Object>();
+                ArrayList<Object> args = (ArrayList<Object>) message;
+                Number identifierArg = (Number) args.get(0);
+                Number resolutionStrategyIdentifierArg = (Number) args.get(1);
+                Number aspectRatioStrategyIdentifierArg = (Number) args.get(2);
+                try {
+                  api.create(
+                      (identifierArg == null) ? null : identifierArg.longValue(),
+                      (resolutionStrategyIdentifierArg == null)
+                          ? null
+                          : resolutionStrategyIdentifierArg.longValue(),
+                      (aspectRatioStrategyIdentifierArg == null)
+                          ? null
+                          : aspectRatioStrategyIdentifierArg.longValue());
+                  wrapped.add(0, null);
+                } catch (Throwable exception) {
+                  ArrayList<Object> wrappedError = wrapError(exception);
+                  wrapped = wrappedError;
+                }
+                reply.reply(wrapped);
+              });
+        } else {
+          channel.setMessageHandler(null);
+        }
+      }
+    }
+  }
+  /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
+  public interface AspectRatioStrategyHostApi {
+
+    void create(
+        @NonNull Long identifier, @NonNull Long preferredAspectRatio, @NonNull Long fallbackRule);
+
+    /** The codec used by AspectRatioStrategyHostApi. */
+    static @NonNull MessageCodec<Object> getCodec() {
+      return new StandardMessageCodec();
+    }
+    /**
+     * Sets up an instance of `AspectRatioStrategyHostApi` to handle messages through the
+     * `binaryMessenger`.
+     */
+    static void setup(
+        @NonNull BinaryMessenger binaryMessenger, @Nullable AspectRatioStrategyHostApi api) {
+      {
+        BasicMessageChannel<Object> channel =
+            new BasicMessageChannel<>(
+                binaryMessenger,
+                "dev.flutter.pigeon.AspectRatioStrategyHostApi.create",
+                getCodec());
+        if (api != null) {
+          channel.setMessageHandler(
+              (message, reply) -> {
+                ArrayList<Object> wrapped = new ArrayList<Object>();
+                ArrayList<Object> args = (ArrayList<Object>) message;
+                Number identifierArg = (Number) args.get(0);
+                Number preferredAspectRatioArg = (Number) args.get(1);
+                Number fallbackRuleArg = (Number) args.get(2);
+                try {
+                  api.create(
+                      (identifierArg == null) ? null : identifierArg.longValue(),
+                      (preferredAspectRatioArg == null)
+                          ? null
+                          : preferredAspectRatioArg.longValue(),
+                      (fallbackRuleArg == null) ? null : fallbackRuleArg.longValue());
+                  wrapped.add(0, null);
+                } catch (Throwable exception) {
+                  ArrayList<Object> wrappedError = wrapError(exception);
+                  wrapped = wrappedError;
+                }
+                reply.reply(wrapped);
+              });
+        } else {
+          channel.setMessageHandler(null);
+        }
+      }
+    }
+  }
+
   private static class CameraStateFlutterApiCodec extends StandardMessageCodec {
     public static final CameraStateFlutterApiCodec INSTANCE = new CameraStateFlutterApiCodec();
 
@@ -2194,37 +2355,10 @@
           channelReply -> callback.reply(null));
     }
   }
-
-  private static class ImageAnalysisHostApiCodec extends StandardMessageCodec {
-    public static final ImageAnalysisHostApiCodec INSTANCE = new ImageAnalysisHostApiCodec();
-
-    private ImageAnalysisHostApiCodec() {}
-
-    @Override
-    protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
-      switch (type) {
-        case (byte) 128:
-          return ResolutionInfo.fromList((ArrayList<Object>) readValue(buffer));
-        default:
-          return super.readValueOfType(type, buffer);
-      }
-    }
-
-    @Override
-    protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
-      if (value instanceof ResolutionInfo) {
-        stream.write(128);
-        writeValue(stream, ((ResolutionInfo) value).toList());
-      } else {
-        super.writeValue(stream, value);
-      }
-    }
-  }
-
   /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
   public interface ImageAnalysisHostApi {
 
-    void create(@NonNull Long identifier, @Nullable ResolutionInfo targetResolutionIdentifier);
+    void create(@NonNull Long identifier, @Nullable Long resolutionSelectorId);
 
     void setAnalyzer(@NonNull Long identifier, @NonNull Long analyzerIdentifier);
 
@@ -2232,7 +2366,7 @@
 
     /** The codec used by ImageAnalysisHostApi. */
     static @NonNull MessageCodec<Object> getCodec() {
-      return ImageAnalysisHostApiCodec.INSTANCE;
+      return new StandardMessageCodec();
     }
     /**
      * Sets up an instance of `ImageAnalysisHostApi` to handle messages through the
@@ -2250,11 +2384,13 @@
                 ArrayList<Object> wrapped = new ArrayList<Object>();
                 ArrayList<Object> args = (ArrayList<Object>) message;
                 Number identifierArg = (Number) args.get(0);
-                ResolutionInfo targetResolutionIdentifierArg = (ResolutionInfo) args.get(1);
+                Number resolutionSelectorIdArg = (Number) args.get(1);
                 try {
                   api.create(
                       (identifierArg == null) ? null : identifierArg.longValue(),
-                      targetResolutionIdentifierArg);
+                      (resolutionSelectorIdArg == null)
+                          ? null
+                          : resolutionSelectorIdArg.longValue());
                   wrapped.add(0, null);
                 } catch (Throwable exception) {
                   ArrayList<Object> wrappedError = wrapError(exception);
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java
index 5e78617..5849147 100644
--- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java
@@ -9,10 +9,10 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.ImageAnalysis;
+import androidx.camera.core.resolutionselector.ResolutionSelector;
 import androidx.core.content.ContextCompat;
 import io.flutter.plugin.common.BinaryMessenger;
 import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ImageAnalysisHostApi;
-import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionInfo;
 import java.util.Objects;
 
 public class ImageAnalysisHostApiImpl implements ImageAnalysisHostApi {
@@ -38,11 +38,13 @@
 
   /** Creates an {@link ImageAnalysis} instance with the target resolution if specified. */
   @Override
-  public void create(@NonNull Long identifier, @Nullable ResolutionInfo targetResolution) {
+  public void create(@NonNull Long identifier, @Nullable Long resolutionSelectorId) {
     ImageAnalysis.Builder imageAnalysisBuilder = cameraXProxy.createImageAnalysisBuilder();
 
-    if (targetResolution != null) {
-      imageAnalysisBuilder.setTargetResolution(CameraXProxy.sizeFromResolution(targetResolution));
+    if (resolutionSelectorId != null) {
+      ResolutionSelector resolutionSelector =
+          Objects.requireNonNull(instanceManager.getInstance(resolutionSelectorId));
+      imageAnalysisBuilder.setResolutionSelector(resolutionSelector);
     }
 
     ImageAnalysis imageAnalysis = imageAnalysisBuilder.build();
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageCaptureHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageCaptureHostApiImpl.java
index f2e71aa..88ec2de 100644
--- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageCaptureHostApiImpl.java
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageCaptureHostApiImpl.java
@@ -10,6 +10,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.ImageCapture;
 import androidx.camera.core.ImageCaptureException;
+import androidx.camera.core.resolutionselector.ResolutionSelector;
 import io.flutter.plugin.common.BinaryMessenger;
 import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ImageCaptureHostApi;
 import java.io.File;
@@ -52,17 +53,19 @@
    */
   @Override
   public void create(
-      @NonNull Long identifier,
-      @Nullable Long flashMode,
-      @Nullable GeneratedCameraXLibrary.ResolutionInfo targetResolution) {
+      @NonNull Long identifier, @Nullable Long flashMode, @Nullable Long resolutionSelectorId) {
     ImageCapture.Builder imageCaptureBuilder = cameraXProxy.createImageCaptureBuilder();
+
     if (flashMode != null) {
       // This sets the requested flash mode, but may fail silently.
       imageCaptureBuilder.setFlashMode(flashMode.intValue());
     }
-    if (targetResolution != null) {
-      imageCaptureBuilder.setTargetResolution(CameraXProxy.sizeFromResolution(targetResolution));
+    if (resolutionSelectorId != null) {
+      ResolutionSelector resolutionSelector =
+          Objects.requireNonNull(instanceManager.getInstance(resolutionSelectorId));
+      imageCaptureBuilder.setResolutionSelector(resolutionSelector);
     }
+
     ImageCapture imageCapture = imageCaptureBuilder.build();
     instanceManager.addDartCreatedInstance(imageCapture, identifier);
   }
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PreviewHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PreviewHostApiImpl.java
index 6f93fd0..07b581e 100644
--- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PreviewHostApiImpl.java
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PreviewHostApiImpl.java
@@ -12,6 +12,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.Preview;
 import androidx.camera.core.SurfaceRequest;
+import androidx.camera.core.resolutionselector.ResolutionSelector;
 import io.flutter.plugin.common.BinaryMessenger;
 import io.flutter.plugins.camerax.GeneratedCameraXLibrary.PreviewHostApi;
 import io.flutter.view.TextureRegistry;
@@ -38,16 +39,18 @@
   /** Creates a {@link Preview} with the target rotation and resolution if specified. */
   @Override
   public void create(
-      @NonNull Long identifier,
-      @Nullable Long rotation,
-      @Nullable GeneratedCameraXLibrary.ResolutionInfo targetResolution) {
+      @NonNull Long identifier, @Nullable Long rotation, @Nullable Long resolutionSelectorId) {
     Preview.Builder previewBuilder = cameraXProxy.createPreviewBuilder();
+
     if (rotation != null) {
       previewBuilder.setTargetRotation(rotation.intValue());
     }
-    if (targetResolution != null) {
-      previewBuilder.setTargetResolution(CameraXProxy.sizeFromResolution(targetResolution));
+    if (resolutionSelectorId != null) {
+      ResolutionSelector resolutionSelector =
+          Objects.requireNonNull(instanceManager.getInstance(resolutionSelectorId));
+      previewBuilder.setResolutionSelector(resolutionSelector);
     }
+
     Preview preview = previewBuilder.build();
     instanceManager.addDartCreatedInstance(preview, identifier);
   }
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ResolutionSelectorHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ResolutionSelectorHostApiImpl.java
new file mode 100644
index 0000000..be05e1b
--- /dev/null
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ResolutionSelectorHostApiImpl.java
@@ -0,0 +1,87 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.camera.core.resolutionselector.AspectRatioStrategy;
+import androidx.camera.core.resolutionselector.ResolutionSelector;
+import androidx.camera.core.resolutionselector.ResolutionStrategy;
+import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionSelectorHostApi;
+import java.util.Objects;
+
+/**
+ * Host API implementation for {@link ResolutionSelector}.
+ *
+ * <p>This class handles instantiating and adding native object instances that are attached to a
+ * Dart instance or handle method calls on the associated native class or an instance of the class.
+ */
+public class ResolutionSelectorHostApiImpl implements ResolutionSelectorHostApi {
+  private final InstanceManager instanceManager;
+  private final ResolutionSelectorProxy proxy;
+
+  /** Proxy for constructors and static method of {@link ResolutionSelector}. */
+  @VisibleForTesting
+  public static class ResolutionSelectorProxy {
+    /** Creates an instance of {@link ResolutionSelector}. */
+    @NonNull
+    public ResolutionSelector create(
+        @Nullable ResolutionStrategy resolutionStrategy,
+        @Nullable AspectRatioStrategy aspectRatioStrategy) {
+      final ResolutionSelector.Builder builder = new ResolutionSelector.Builder();
+      if (resolutionStrategy != null) {
+        builder.setResolutionStrategy(resolutionStrategy);
+      }
+      if (aspectRatioStrategy != null) {
+        builder.setAspectRatioStrategy(aspectRatioStrategy);
+      }
+      return builder.build();
+    }
+  }
+
+  /**
+   * Constructs a {@link ResolutionSelectorHostApiImpl}.
+   *
+   * @param instanceManager maintains instances stored to communicate with attached Dart objects
+   */
+  public ResolutionSelectorHostApiImpl(@NonNull InstanceManager instanceManager) {
+    this(instanceManager, new ResolutionSelectorProxy());
+  }
+
+  /**
+   * Constructs a {@link ResolutionSelectorHostApiImpl}.
+   *
+   * @param instanceManager maintains instances stored to communicate with attached Dart objects
+   * @param proxy proxy for constructors and static method of {@link ResolutionSelector}
+   */
+  @VisibleForTesting
+  ResolutionSelectorHostApiImpl(
+      @NonNull InstanceManager instanceManager, @NonNull ResolutionSelectorProxy proxy) {
+    this.instanceManager = instanceManager;
+    this.proxy = proxy;
+  }
+
+  /**
+   * Creates a {@link ResolutionSelector} instance with the {@link ResolutionStrategy} and {@link
+   * AspectRatio} that have the identifiers specified if provided.
+   */
+  @Override
+  public void create(
+      @NonNull Long identifier,
+      @Nullable Long resolutionStrategyIdentifier,
+      @Nullable Long aspectRatioStrategyIdentifier) {
+    instanceManager.addDartCreatedInstance(
+        proxy.create(
+            resolutionStrategyIdentifier == null
+                ? null
+                : Objects.requireNonNull(instanceManager.getInstance(resolutionStrategyIdentifier)),
+            aspectRatioStrategyIdentifier == null
+                ? null
+                : Objects.requireNonNull(
+                    instanceManager.getInstance(aspectRatioStrategyIdentifier))),
+        identifier);
+  }
+}
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ResolutionStrategyHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ResolutionStrategyHostApiImpl.java
new file mode 100644
index 0000000..c110c40
--- /dev/null
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ResolutionStrategyHostApiImpl.java
@@ -0,0 +1,81 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import android.util.Size;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.camera.core.resolutionselector.ResolutionStrategy;
+import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionStrategyHostApi;
+
+/**
+ * Host API implementation for {@link ResolutionStrategy}.
+ *
+ * <p>This class handles instantiating and adding native object instances that are attached to a
+ * Dart instance or handle method calls on the associated native class or an instance of the class.
+ */
+public class ResolutionStrategyHostApiImpl implements ResolutionStrategyHostApi {
+  private final InstanceManager instanceManager;
+  private final ResolutionStrategyProxy proxy;
+
+  /** Proxy for constructors and static method of {@link ResolutionStrategy}. */
+  @VisibleForTesting
+  public static class ResolutionStrategyProxy {
+
+    /** Creates an instance of {@link ResolutionStrategy}. */
+    @NonNull
+    public ResolutionStrategy create(@NonNull Size boundSize, @NonNull Long fallbackRule) {
+      return new ResolutionStrategy(boundSize, fallbackRule.intValue());
+    }
+  }
+
+  /**
+   * Constructs a {@link ResolutionStrategyHostApiImpl}.
+   *
+   * @param instanceManager maintains instances stored to communicate with attached Dart objects
+   */
+  public ResolutionStrategyHostApiImpl(@NonNull InstanceManager instanceManager) {
+    this(instanceManager, new ResolutionStrategyProxy());
+  }
+
+  /**
+   * Constructs a {@link ResolutionStrategyHostApiImpl}.
+   *
+   * @param instanceManager maintains instances stored to communicate with attached Dart objects
+   * @param proxy proxy for constructors and static method of {@link ResolutionStrategy}
+   */
+  @VisibleForTesting
+  ResolutionStrategyHostApiImpl(
+      @NonNull InstanceManager instanceManager, @NonNull ResolutionStrategyProxy proxy) {
+    this.instanceManager = instanceManager;
+    this.proxy = proxy;
+  }
+
+  /**
+   * Creates a {@link ResolutionStrategy} instance with the {@link
+   * GeneratedCameraXLibrary.ResolutionInfo} bound size and {@code fallbackRule} if specified.
+   */
+  @Override
+  public void create(
+      @NonNull Long identifier,
+      @Nullable GeneratedCameraXLibrary.ResolutionInfo boundSize,
+      @Nullable Long fallbackRule) {
+    ResolutionStrategy resolutionStrategy;
+    if (boundSize == null && fallbackRule == null) {
+      // Strategy that chooses the highest available resolution does not have a bound size or fallback rule.
+      resolutionStrategy = ResolutionStrategy.HIGHEST_AVAILABLE_STRATEGY;
+    } else if (boundSize == null) {
+      throw new IllegalArgumentException(
+          "A bound size must be specified if a non-null fallback rule is specified to create a valid ResolutionStrategy.");
+    } else {
+      resolutionStrategy =
+          proxy.create(
+              new Size(boundSize.getWidth().intValue(), boundSize.getHeight().intValue()),
+              fallbackRule);
+    }
+    instanceManager.addDartCreatedInstance(resolutionStrategy, identifier);
+  }
+}
diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/AspectRatioStrategyTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/AspectRatioStrategyTest.java
new file mode 100644
index 0000000..02e757d
--- /dev/null
+++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/AspectRatioStrategyTest.java
@@ -0,0 +1,51 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+import androidx.camera.core.resolutionselector.AspectRatioStrategy;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+public class AspectRatioStrategyTest {
+  @Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
+  @Mock public AspectRatioStrategy mockAspectRatioStrategy;
+  @Mock public AspectRatioStrategyHostApiImpl.AspectRatioStrategyProxy mockProxy;
+
+  InstanceManager instanceManager;
+
+  @Before
+  public void setUp() {
+    instanceManager = InstanceManager.create(identifier -> {});
+  }
+
+  @After
+  public void tearDown() {
+    instanceManager.stopFinalizationListener();
+  }
+
+  @Test
+  public void hostApiCreate_createsExpectedAspectRatioStrategyInstance() {
+    final Long preferredAspectRatio = 0L;
+    final Long fallbackRule = 1L;
+
+    when(mockProxy.create(preferredAspectRatio, fallbackRule)).thenReturn(mockAspectRatioStrategy);
+
+    final AspectRatioStrategyHostApiImpl hostApi =
+        new AspectRatioStrategyHostApiImpl(instanceManager, mockProxy);
+
+    final long instanceIdentifier = 0;
+    hostApi.create(instanceIdentifier, preferredAspectRatio, fallbackRule);
+
+    assertEquals(instanceManager.getInstance(instanceIdentifier), mockAspectRatioStrategy);
+  }
+}
diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageAnalysisTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageAnalysisTest.java
index 38f7776..b9a6d29 100644
--- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageAnalysisTest.java
+++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageAnalysisTest.java
@@ -12,18 +12,16 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.util.Size;
 import androidx.camera.core.ImageAnalysis;
+import androidx.camera.core.resolutionselector.ResolutionSelector;
 import androidx.test.core.app.ApplicationProvider;
 import io.flutter.plugin.common.BinaryMessenger;
-import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionInfo;
 import java.util.concurrent.Executor;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
@@ -55,27 +53,19 @@
         new ImageAnalysisHostApiImpl(mockBinaryMessenger, instanceManager);
     final CameraXProxy mockCameraXProxy = mock(CameraXProxy.class);
     final ImageAnalysis.Builder mockImageAnalysisBuilder = mock(ImageAnalysis.Builder.class);
-    final int targetResolutionWidth = 10;
-    final int targetResolutionHeight = 50;
-    final ResolutionInfo resolutionInfo =
-        new ResolutionInfo.Builder()
-            .setWidth(Long.valueOf(targetResolutionWidth))
-            .setHeight(Long.valueOf(targetResolutionHeight))
-            .build();
+    final ResolutionSelector mockResolutionSelector = mock(ResolutionSelector.class);
     final long instanceIdentifier = 0;
+    final long mockResolutionSelectorId = 25;
 
     hostApi.cameraXProxy = mockCameraXProxy;
-
-    final ArgumentCaptor<Size> sizeCaptor = ArgumentCaptor.forClass(Size.class);
+    instanceManager.addDartCreatedInstance(mockResolutionSelector, mockResolutionSelectorId);
 
     when(mockCameraXProxy.createImageAnalysisBuilder()).thenReturn(mockImageAnalysisBuilder);
     when(mockImageAnalysisBuilder.build()).thenReturn(mockImageAnalysis);
 
-    hostApi.create(instanceIdentifier, resolutionInfo);
+    hostApi.create(instanceIdentifier, mockResolutionSelectorId);
 
-    verify(mockImageAnalysisBuilder).setTargetResolution(sizeCaptor.capture());
-    assertEquals(sizeCaptor.getValue().getWidth(), targetResolutionWidth);
-    assertEquals(sizeCaptor.getValue().getHeight(), targetResolutionHeight);
+    verify(mockImageAnalysisBuilder).setResolutionSelector(mockResolutionSelector);
     assertEquals(instanceManager.getInstance(instanceIdentifier), mockImageAnalysis);
   }
 
diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageCaptureTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageCaptureTest.java
index 881b6be..df6c8ee 100644
--- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageCaptureTest.java
+++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageCaptureTest.java
@@ -4,7 +4,6 @@
 
 package io.flutter.plugins.camerax;
 
-import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
@@ -15,9 +14,9 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.util.Size;
 import androidx.camera.core.ImageCapture;
 import androidx.camera.core.ImageCaptureException;
+import androidx.camera.core.resolutionselector.ResolutionSelector;
 import io.flutter.plugin.common.BinaryMessenger;
 import java.io.File;
 import java.io.IOException;
@@ -27,7 +26,6 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockedStatic;
 import org.mockito.junit.MockitoJUnit;
@@ -66,26 +64,18 @@
     final ImageCapture.Builder mockImageCaptureBuilder = mock(ImageCapture.Builder.class);
     final Long imageCaptureIdentifier = 74L;
     final Long flashMode = Long.valueOf(ImageCapture.FLASH_MODE_ON);
-    final int targetResolutionWidth = 10;
-    final int targetResolutionHeight = 50;
-    final GeneratedCameraXLibrary.ResolutionInfo resolutionInfo =
-        new GeneratedCameraXLibrary.ResolutionInfo.Builder()
-            .setWidth(Long.valueOf(targetResolutionWidth))
-            .setHeight(Long.valueOf(targetResolutionHeight))
-            .build();
+    final ResolutionSelector mockResolutionSelector = mock(ResolutionSelector.class);
+    final long mockResolutionSelectorId = 77;
 
     imageCaptureHostApiImpl.cameraXProxy = mockCameraXProxy;
+    testInstanceManager.addDartCreatedInstance(mockResolutionSelector, mockResolutionSelectorId);
     when(mockCameraXProxy.createImageCaptureBuilder()).thenReturn(mockImageCaptureBuilder);
     when(mockImageCaptureBuilder.build()).thenReturn(mockImageCapture);
 
-    final ArgumentCaptor<Size> sizeCaptor = ArgumentCaptor.forClass(Size.class);
-
-    imageCaptureHostApiImpl.create(imageCaptureIdentifier, flashMode, resolutionInfo);
+    imageCaptureHostApiImpl.create(imageCaptureIdentifier, flashMode, mockResolutionSelectorId);
 
     verify(mockImageCaptureBuilder).setFlashMode(flashMode.intValue());
-    verify(mockImageCaptureBuilder).setTargetResolution(sizeCaptor.capture());
-    assertEquals(sizeCaptor.getValue().getWidth(), targetResolutionWidth);
-    assertEquals(sizeCaptor.getValue().getHeight(), targetResolutionHeight);
+    verify(mockImageCaptureBuilder).setResolutionSelector(mockResolutionSelector);
     verify(mockImageCaptureBuilder).build();
     verify(testInstanceManager).addDartCreatedInstance(mockImageCapture, imageCaptureIdentifier);
   }
diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PreviewTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PreviewTest.java
index 39b73ab..37a7c77 100644
--- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PreviewTest.java
+++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PreviewTest.java
@@ -18,6 +18,7 @@
 import android.view.Surface;
 import androidx.camera.core.Preview;
 import androidx.camera.core.SurfaceRequest;
+import androidx.camera.core.resolutionselector.ResolutionSelector;
 import androidx.core.util.Consumer;
 import io.flutter.plugin.common.BinaryMessenger;
 import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionInfo;
@@ -63,27 +64,20 @@
         new PreviewHostApiImpl(mockBinaryMessenger, testInstanceManager, mockTextureRegistry);
     final Preview.Builder mockPreviewBuilder = mock(Preview.Builder.class);
     final int targetRotation = 90;
-    final int targetResolutionWidth = 10;
-    final int targetResolutionHeight = 50;
     final Long previewIdentifier = 3L;
-    final GeneratedCameraXLibrary.ResolutionInfo resolutionInfo =
-        new GeneratedCameraXLibrary.ResolutionInfo.Builder()
-            .setWidth(Long.valueOf(targetResolutionWidth))
-            .setHeight(Long.valueOf(targetResolutionHeight))
-            .build();
+    final ResolutionSelector mockResolutionSelector = mock(ResolutionSelector.class);
+    final long mockResolutionSelectorId = 90;
 
     previewHostApi.cameraXProxy = mockCameraXProxy;
+    testInstanceManager.addDartCreatedInstance(mockResolutionSelector, mockResolutionSelectorId);
     when(mockCameraXProxy.createPreviewBuilder()).thenReturn(mockPreviewBuilder);
     when(mockPreviewBuilder.build()).thenReturn(mockPreview);
 
-    final ArgumentCaptor<Size> sizeCaptor = ArgumentCaptor.forClass(Size.class);
-
-    previewHostApi.create(previewIdentifier, Long.valueOf(targetRotation), resolutionInfo);
+    previewHostApi.create(
+        previewIdentifier, Long.valueOf(targetRotation), mockResolutionSelectorId);
 
     verify(mockPreviewBuilder).setTargetRotation(targetRotation);
-    verify(mockPreviewBuilder).setTargetResolution(sizeCaptor.capture());
-    assertEquals(sizeCaptor.getValue().getWidth(), targetResolutionWidth);
-    assertEquals(sizeCaptor.getValue().getHeight(), targetResolutionHeight);
+    verify(mockPreviewBuilder).setResolutionSelector(mockResolutionSelector);
     verify(mockPreviewBuilder).build();
     verify(testInstanceManager).addDartCreatedInstance(mockPreview, previewIdentifier);
   }
diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ResolutionSelectorTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ResolutionSelectorTest.java
new file mode 100644
index 0000000..f323e47
--- /dev/null
+++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ResolutionSelectorTest.java
@@ -0,0 +1,59 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import androidx.camera.core.resolutionselector.AspectRatioStrategy;
+import androidx.camera.core.resolutionselector.ResolutionSelector;
+import androidx.camera.core.resolutionselector.ResolutionStrategy;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+public class ResolutionSelectorTest {
+  @Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
+  @Mock public ResolutionSelector mockResolutionSelector;
+  @Mock public ResolutionSelectorHostApiImpl.ResolutionSelectorProxy mockProxy;
+
+  InstanceManager instanceManager;
+
+  @Before
+  public void setUp() {
+    instanceManager = InstanceManager.create(identifier -> {});
+  }
+
+  @After
+  public void tearDown() {
+    instanceManager.stopFinalizationListener();
+  }
+
+  @Test
+  public void hostApiCreate_createsExpectedResolutionSelectorInstance() {
+    final ResolutionStrategy mockResolutionStrategy = mock(ResolutionStrategy.class);
+    final long resolutionStrategyIdentifier = 14;
+    instanceManager.addDartCreatedInstance(mockResolutionStrategy, resolutionStrategyIdentifier);
+
+    final AspectRatioStrategy mockAspectRatioStrategy = mock(AspectRatioStrategy.class);
+    final long aspectRatioStrategyIdentifier = 15;
+    instanceManager.addDartCreatedInstance(mockAspectRatioStrategy, aspectRatioStrategyIdentifier);
+
+    when(mockProxy.create(mockResolutionStrategy, mockAspectRatioStrategy))
+        .thenReturn(mockResolutionSelector);
+    final ResolutionSelectorHostApiImpl hostApi =
+        new ResolutionSelectorHostApiImpl(instanceManager, mockProxy);
+
+    final long instanceIdentifier = 0;
+    hostApi.create(instanceIdentifier, resolutionStrategyIdentifier, aspectRatioStrategyIdentifier);
+
+    assertEquals(instanceManager.getInstance(instanceIdentifier), mockResolutionSelector);
+  }
+}
diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ResolutionStrategyTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ResolutionStrategyTest.java
new file mode 100644
index 0000000..7bbc615
--- /dev/null
+++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ResolutionStrategyTest.java
@@ -0,0 +1,71 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.util.Size;
+import androidx.camera.core.resolutionselector.ResolutionStrategy;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+public class ResolutionStrategyTest {
+  @Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
+  @Mock public ResolutionStrategy mockResolutionStrategy;
+  @Mock public ResolutionStrategyHostApiImpl.ResolutionStrategyProxy mockProxy;
+
+  InstanceManager instanceManager;
+
+  @Before
+  public void setUp() {
+    instanceManager = InstanceManager.create(identifier -> {});
+  }
+
+  @After
+  public void tearDown() {
+    instanceManager.stopFinalizationListener();
+  }
+
+  @Test
+  public void hostApiCreate_createsExpectedResolutionStrategyInstanceWhenArgumentsValid() {
+    final GeneratedCameraXLibrary.ResolutionInfo boundSize =
+        new GeneratedCameraXLibrary.ResolutionInfo.Builder().setWidth(50L).setHeight(30L).build();
+
+    final Long fallbackRule = 0L;
+
+    when(mockProxy.create(any(Size.class), eq(fallbackRule))).thenReturn(mockResolutionStrategy);
+
+    final ResolutionStrategyHostApiImpl hostApi =
+        new ResolutionStrategyHostApiImpl(instanceManager, mockProxy);
+
+    final long instanceIdentifier = 0;
+    hostApi.create(instanceIdentifier, boundSize, fallbackRule);
+
+    assertEquals(instanceManager.getInstance(instanceIdentifier), mockResolutionStrategy);
+  }
+
+  @Test
+  public void hostApiCreate_throwsAssertionErrorWhenArgumentsInvalid() {
+    final Long fallbackRule = 8L;
+    final long instanceIdentifier = 0;
+
+    final ResolutionStrategyHostApiImpl hostApi =
+        new ResolutionStrategyHostApiImpl(instanceManager, mockProxy);
+
+    // We expect an exception to be thrown if fallback rule is specified but bound size is not.
+    assertThrows(
+        IllegalArgumentException.class,
+        () -> hostApi.create(instanceIdentifier, null, fallbackRule));
+  }
+}
diff --git a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart
index 9a58e6f..7c5bf6b 100644
--- a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart
+++ b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart
@@ -116,10 +116,6 @@
   @visibleForTesting
   CameraSelector? cameraSelector;
 
-  /// The resolution preset used to create a camera that should be used for
-  /// capturing still images and recording video.
-  ResolutionPreset? _resolutionPreset;
-
   /// The controller we need to broadcast the different camera events.
   ///
   /// It is a `broadcast` because multiple controllers will connect to
@@ -233,19 +229,17 @@
     processCameraProvider ??= await ProcessCameraProvider.getInstance();
     processCameraProvider!.unbindAll();
 
+    // TODO(camsim99): Implement resolution configuration for UseCases
+    // configured here. https://github.com/flutter/flutter/issues/120462
+
     // Configure Preview instance.
-    _resolutionPreset = resolutionPreset;
     final int targetRotation =
         _getTargetRotation(cameraDescription.sensorOrientation);
-    final ResolutionInfo? previewTargetResolution =
-        _getTargetResolutionForPreview(resolutionPreset);
-    preview = createPreview(targetRotation, previewTargetResolution);
+    preview = createPreview(targetRotation);
     final int flutterSurfaceTextureId = await preview!.setSurfaceProvider();
 
     // Configure ImageCapture instance.
-    final ResolutionInfo? imageCaptureTargetResolution =
-        _getTargetResolutionForImageCapture(_resolutionPreset);
-    imageCapture = createImageCapture(null, imageCaptureTargetResolution);
+    imageCapture = createImageCapture(null);
 
     // Configure VideoCapture and Recorder instances.
     // TODO(gmackall): Enable video capture resolution configuration in createRecorder().
@@ -642,7 +636,7 @@
 
     // TODO(camsim99): Support resolution configuration.
     // Defaults to YUV_420_888 image format.
-    imageAnalysis ??= createImageAnalysis(null);
+    imageAnalysis ??= createImageAnalysis();
     unawaited(imageAnalysis!.setAnalyzer(analyzer));
 
     if (await processCameraProvider!.isBound(imageAnalysis!)) {
@@ -780,23 +774,6 @@
     }
   }
 
-  /// Returns [ResolutionInfo] that maps to the specified resolution preset for
-  /// a camera preview.
-  ResolutionInfo? _getTargetResolutionForPreview(ResolutionPreset? resolution) {
-    // TODO(camsim99): Implement resolution configuration.
-    // https://github.com/flutter/flutter/issues/120462
-    return null;
-  }
-
-  /// Returns [ResolutionInfo] that maps to the specified resolution preset for
-  /// image capture.
-  ResolutionInfo? _getTargetResolutionForImageCapture(
-      ResolutionPreset? resolution) {
-    // TODO(camsim99): Implement resolution configuration.
-    // https://github.com/flutter/flutter/issues/120462
-    return null;
-  }
-
   // Methods for calls that need to be tested:
 
   /// Requests camera permissions.
@@ -829,18 +806,15 @@
   /// Returns a [Preview] configured with the specified target rotation and
   /// resolution.
   @visibleForTesting
-  Preview createPreview(int targetRotation, ResolutionInfo? targetResolution) {
-    return Preview(
-        targetRotation: targetRotation, targetResolution: targetResolution);
+  Preview createPreview(int targetRotation) {
+    return Preview(targetRotation: targetRotation);
   }
 
   /// Returns an [ImageCapture] configured with specified flash mode and
   /// target resolution.
   @visibleForTesting
-  ImageCapture createImageCapture(
-      int? flashMode, ResolutionInfo? targetResolution) {
-    return ImageCapture(
-        targetFlashMode: flashMode, targetResolution: targetResolution);
+  ImageCapture createImageCapture(int? flashMode) {
+    return ImageCapture(targetFlashMode: flashMode);
   }
 
   /// Returns a [Recorder] for use in video capture.
@@ -857,7 +831,7 @@
 
   /// Returns an [ImageAnalysis] configured with specified target resolution.
   @visibleForTesting
-  ImageAnalysis createImageAnalysis(ResolutionInfo? targetResolution) {
-    return ImageAnalysis(targetResolution: targetResolution);
+  ImageAnalysis createImageAnalysis() {
+    return ImageAnalysis();
   }
 }
diff --git a/packages/camera/camera_android_camerax/lib/src/aspect_ratio_strategy.dart b/packages/camera/camera_android_camerax/lib/src/aspect_ratio_strategy.dart
new file mode 100644
index 0000000..621f4dd
--- /dev/null
+++ b/packages/camera/camera_android_camerax/lib/src/aspect_ratio_strategy.dart
@@ -0,0 +1,138 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/services.dart';
+import 'package:meta/meta.dart' show immutable;
+
+import 'camerax_library.g.dart';
+import 'instance_manager.dart';
+import 'java_object.dart';
+
+/// The aspect ratio of a UseCase.
+///
+/// Aspect ratio is the ratio of width to height.
+///
+/// See https://developer.android.com/reference/androidx/camera/core/AspectRatio.
+class AspectRatio {
+  AspectRatio._();
+
+  /// 4:3 standard aspect ratio.
+  ///
+  /// See https://developer.android.com/reference/androidx/camera/core/AspectRatio#RATIO_4_3().
+  static const int ratio4To3 = 0;
+
+  /// 16:9 standard aspect ratio.
+  ///
+  /// See https://developer.android.com/reference/androidx/camera/core/AspectRatio#RATIO_16_9().
+  static const int ratio16To9 = 1;
+
+  /// The aspect ratio representing no preference for aspect ratio.
+  ///
+  /// See https://developer.android.com/reference/androidx/camera/core/AspectRatio#RATIO_DEFAULT().
+  static const int ratioDefault = -1;
+}
+
+/// The aspect ratio strategy defines the sequence of aspect ratios that are
+/// used to select the best size for a particular image.
+///
+/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/AspectRatioStrategy.
+@immutable
+class AspectRatioStrategy extends JavaObject {
+  /// Construct a [AspectRatioStrategy].
+  AspectRatioStrategy({
+    required this.preferredAspectRatio,
+    required this.fallbackRule,
+    super.binaryMessenger,
+    super.instanceManager,
+  })  : _api = _AspectRatioStrategyHostApiImpl(
+          instanceManager: instanceManager,
+          binaryMessenger: binaryMessenger,
+        ),
+        super.detached() {
+    _api.createFromInstances(this, preferredAspectRatio, fallbackRule);
+  }
+
+  /// Instantiates a [AspectRatioStrategy] without creating and attaching to an
+  /// instance of the associated native class.
+  ///
+  /// This should only be used outside of tests by subclasses created by this
+  /// library or to create a copy for an [InstanceManager].
+  AspectRatioStrategy.detached({
+    required this.preferredAspectRatio,
+    required this.fallbackRule,
+    super.binaryMessenger,
+    super.instanceManager,
+  })  : _api = _AspectRatioStrategyHostApiImpl(
+          instanceManager: instanceManager,
+          binaryMessenger: binaryMessenger,
+        ),
+        super.detached();
+
+  /// CameraX doesn't fall back to select sizes of any other aspect ratio when
+  /// this fallback rule is used.
+  ///
+  /// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/AspectRatioStrategy#FALLBACK_RULE_NONE().
+  static const int fallbackRuleNone = 0;
+
+  /// CameraX automatically chooses the next best aspect ratio which contains
+  /// the closest field of view (FOV) of the camera sensor, from the remaining
+  /// options.
+  ///
+  /// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/AspectRatioStrategy#FALLBACK_RULE_AUTO().
+  static const int fallbackRuleAuto = 1;
+
+  final _AspectRatioStrategyHostApiImpl _api;
+
+  /// The preferred aspect ratio captured by the camera.
+  final int preferredAspectRatio;
+
+  /// The specified fallback rule for choosing the aspect ratio when the
+  /// preferred aspect ratio is not available.
+  final int fallbackRule;
+}
+
+/// Host API implementation of [AspectRatioStrategy].
+class _AspectRatioStrategyHostApiImpl extends AspectRatioStrategyHostApi {
+  /// Constructs an [_AspectRatioStrategyHostApiImpl].
+  ///
+  /// If [binaryMessenger] is null, the default [BinaryMessenger] will be used,
+  /// which routes to the host platform.
+  ///
+  /// An [instanceManager] is typically passed when a copy of an instance
+  /// contained by an [InstanceManager] is being created. If left null, it
+  /// will default to the global instance defined in [JavaObject].
+  _AspectRatioStrategyHostApiImpl({
+    this.binaryMessenger,
+    InstanceManager? instanceManager,
+  })  : instanceManager = instanceManager ?? JavaObject.globalInstanceManager,
+        super(binaryMessenger: binaryMessenger);
+
+  /// Receives binary data across the Flutter platform barrier.
+  final BinaryMessenger? binaryMessenger;
+
+  /// Maintains instances stored to communicate with native language objects.
+  final InstanceManager instanceManager;
+
+  /// Creates a [AspectRatioStrategy] on the native side with the preferred
+  /// aspect ratio and fallback rule specified.
+  Future<void> createFromInstances(
+    AspectRatioStrategy instance,
+    int preferredAspectRatio,
+    int fallbackRule,
+  ) {
+    return create(
+      instanceManager.addDartCreatedInstance(
+        instance,
+        onCopy: (AspectRatioStrategy original) => AspectRatioStrategy.detached(
+          preferredAspectRatio: original.preferredAspectRatio,
+          fallbackRule: original.fallbackRule,
+          binaryMessenger: binaryMessenger,
+          instanceManager: instanceManager,
+        ),
+      ),
+      preferredAspectRatio,
+      fallbackRule,
+    );
+  }
+}
diff --git a/packages/camera/camera_android_camerax/lib/src/camerax_library.g.dart b/packages/camera/camera_android_camerax/lib/src/camerax_library.g.dart
index 2a1b281..2d1dccf 100644
--- a/packages/camera/camera_android_camerax/lib/src/camerax_library.g.dart
+++ b/packages/camera/camera_android_camerax/lib/src/camerax_library.g.dart
@@ -22,6 +22,22 @@
   pendingOpen,
 }
 
+/// The types (T) properly wrapped to be used as a LiveData<T>.
+///
+/// If you need to add another type to support a type S to use a LiveData<S> in
+/// this plugin, ensure the following is done on the Dart side:
+///
+///  * In `../lib/src/live_data.dart`, add new cases for S in
+///    `_LiveDataHostApiImpl#getValueFromInstances` to get the current value of
+///    type S from a LiveData<S> instance and in `LiveDataFlutterApiImpl#create`
+///    to create the expected type of LiveData<S> when requested.
+///
+/// On the native side, ensure the following is done:
+///
+///  * Update `LiveDataHostApiImpl#getValue` is updated to properly return
+///    identifiers for instances of type S.
+///  * Update `ObserverFlutterApiWrapper#onChanged` to properly handle receiving
+///    calls with instances of type S if a LiveData<S> instance is observed.
 enum LiveDataSupportedType {
   cameraState,
   zoomState,
@@ -937,9 +953,6 @@
     if (value is ResolutionInfo) {
       buffer.putUint8(128);
       writeValue(buffer, value.encode());
-    } else if (value is ResolutionInfo) {
-      buffer.putUint8(129);
-      writeValue(buffer, value.encode());
     } else {
       super.writeValue(buffer, value);
     }
@@ -950,8 +963,6 @@
     switch (type) {
       case 128:
         return ResolutionInfo.decode(readValue(buffer)!);
-      case 129:
-        return ResolutionInfo.decode(readValue(buffer)!);
       default:
         return super.readValueOfType(type, buffer);
     }
@@ -969,12 +980,12 @@
   static const MessageCodec<Object?> codec = _PreviewHostApiCodec();
 
   Future<void> create(int arg_identifier, int? arg_rotation,
-      ResolutionInfo? arg_targetResolution) async {
+      int? arg_resolutionSelectorId) async {
     final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
         'dev.flutter.pigeon.PreviewHostApi.create', codec,
         binaryMessenger: _binaryMessenger);
-    final List<Object?>? replyList = await channel
-            .send(<Object?>[arg_identifier, arg_rotation, arg_targetResolution])
+    final List<Object?>? replyList = await channel.send(
+            <Object?>[arg_identifier, arg_rotation, arg_resolutionSelectorId])
         as List<Object?>?;
     if (replyList == null) {
       throw PlatformException(
@@ -1505,29 +1516,6 @@
   }
 }
 
-class _ImageCaptureHostApiCodec extends StandardMessageCodec {
-  const _ImageCaptureHostApiCodec();
-  @override
-  void writeValue(WriteBuffer buffer, Object? value) {
-    if (value is ResolutionInfo) {
-      buffer.putUint8(128);
-      writeValue(buffer, value.encode());
-    } else {
-      super.writeValue(buffer, value);
-    }
-  }
-
-  @override
-  Object? readValueOfType(int type, ReadBuffer buffer) {
-    switch (type) {
-      case 128:
-        return ResolutionInfo.decode(readValue(buffer)!);
-      default:
-        return super.readValueOfType(type, buffer);
-    }
-  }
-}
-
 class ImageCaptureHostApi {
   /// Constructor for [ImageCaptureHostApi].  The [binaryMessenger] named argument is
   /// available for dependency injection.  If it is left null, the default
@@ -1536,15 +1524,15 @@
       : _binaryMessenger = binaryMessenger;
   final BinaryMessenger? _binaryMessenger;
 
-  static const MessageCodec<Object?> codec = _ImageCaptureHostApiCodec();
+  static const MessageCodec<Object?> codec = StandardMessageCodec();
 
   Future<void> create(int arg_identifier, int? arg_flashMode,
-      ResolutionInfo? arg_targetResolution) async {
+      int? arg_resolutionSelectorId) async {
     final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
         'dev.flutter.pigeon.ImageCaptureHostApi.create', codec,
         binaryMessenger: _binaryMessenger);
     final List<Object?>? replyList = await channel.send(
-            <Object?>[arg_identifier, arg_flashMode, arg_targetResolution])
+            <Object?>[arg_identifier, arg_flashMode, arg_resolutionSelectorId])
         as List<Object?>?;
     if (replyList == null) {
       throw PlatformException(
@@ -1612,6 +1600,138 @@
   }
 }
 
+class _ResolutionStrategyHostApiCodec extends StandardMessageCodec {
+  const _ResolutionStrategyHostApiCodec();
+  @override
+  void writeValue(WriteBuffer buffer, Object? value) {
+    if (value is ResolutionInfo) {
+      buffer.putUint8(128);
+      writeValue(buffer, value.encode());
+    } else {
+      super.writeValue(buffer, value);
+    }
+  }
+
+  @override
+  Object? readValueOfType(int type, ReadBuffer buffer) {
+    switch (type) {
+      case 128:
+        return ResolutionInfo.decode(readValue(buffer)!);
+      default:
+        return super.readValueOfType(type, buffer);
+    }
+  }
+}
+
+class ResolutionStrategyHostApi {
+  /// Constructor for [ResolutionStrategyHostApi].  The [binaryMessenger] named argument is
+  /// available for dependency injection.  If it is left null, the default
+  /// BinaryMessenger will be used which routes to the host platform.
+  ResolutionStrategyHostApi({BinaryMessenger? binaryMessenger})
+      : _binaryMessenger = binaryMessenger;
+  final BinaryMessenger? _binaryMessenger;
+
+  static const MessageCodec<Object?> codec = _ResolutionStrategyHostApiCodec();
+
+  Future<void> create(int arg_identifier, ResolutionInfo? arg_boundSize,
+      int? arg_fallbackRule) async {
+    final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+        'dev.flutter.pigeon.ResolutionStrategyHostApi.create', codec,
+        binaryMessenger: _binaryMessenger);
+    final List<Object?>? replyList = await channel
+            .send(<Object?>[arg_identifier, arg_boundSize, arg_fallbackRule])
+        as List<Object?>?;
+    if (replyList == null) {
+      throw PlatformException(
+        code: 'channel-error',
+        message: 'Unable to establish connection on channel.',
+      );
+    } else if (replyList.length > 1) {
+      throw PlatformException(
+        code: replyList[0]! as String,
+        message: replyList[1] as String?,
+        details: replyList[2],
+      );
+    } else {
+      return;
+    }
+  }
+}
+
+class ResolutionSelectorHostApi {
+  /// Constructor for [ResolutionSelectorHostApi].  The [binaryMessenger] named argument is
+  /// available for dependency injection.  If it is left null, the default
+  /// BinaryMessenger will be used which routes to the host platform.
+  ResolutionSelectorHostApi({BinaryMessenger? binaryMessenger})
+      : _binaryMessenger = binaryMessenger;
+  final BinaryMessenger? _binaryMessenger;
+
+  static const MessageCodec<Object?> codec = StandardMessageCodec();
+
+  Future<void> create(int arg_identifier, int? arg_resolutionStrategyIdentifier,
+      int? arg_aspectRatioStrategyIdentifier) async {
+    final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+        'dev.flutter.pigeon.ResolutionSelectorHostApi.create', codec,
+        binaryMessenger: _binaryMessenger);
+    final List<Object?>? replyList = await channel.send(<Object?>[
+      arg_identifier,
+      arg_resolutionStrategyIdentifier,
+      arg_aspectRatioStrategyIdentifier
+    ]) as List<Object?>?;
+    if (replyList == null) {
+      throw PlatformException(
+        code: 'channel-error',
+        message: 'Unable to establish connection on channel.',
+      );
+    } else if (replyList.length > 1) {
+      throw PlatformException(
+        code: replyList[0]! as String,
+        message: replyList[1] as String?,
+        details: replyList[2],
+      );
+    } else {
+      return;
+    }
+  }
+}
+
+class AspectRatioStrategyHostApi {
+  /// Constructor for [AspectRatioStrategyHostApi].  The [binaryMessenger] named argument is
+  /// available for dependency injection.  If it is left null, the default
+  /// BinaryMessenger will be used which routes to the host platform.
+  AspectRatioStrategyHostApi({BinaryMessenger? binaryMessenger})
+      : _binaryMessenger = binaryMessenger;
+  final BinaryMessenger? _binaryMessenger;
+
+  static const MessageCodec<Object?> codec = StandardMessageCodec();
+
+  Future<void> create(int arg_identifier, int arg_preferredAspectRatio,
+      int arg_fallbackRule) async {
+    final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+        'dev.flutter.pigeon.AspectRatioStrategyHostApi.create', codec,
+        binaryMessenger: _binaryMessenger);
+    final List<Object?>? replyList = await channel.send(<Object?>[
+      arg_identifier,
+      arg_preferredAspectRatio,
+      arg_fallbackRule
+    ]) as List<Object?>?;
+    if (replyList == null) {
+      throw PlatformException(
+        code: 'channel-error',
+        message: 'Unable to establish connection on channel.',
+      );
+    } else if (replyList.length > 1) {
+      throw PlatformException(
+        code: replyList[0]! as String,
+        message: replyList[1] as String?,
+        details: replyList[2],
+      );
+    } else {
+      return;
+    }
+  }
+}
+
 class _CameraStateFlutterApiCodec extends StandardMessageCodec {
   const _CameraStateFlutterApiCodec();
   @override
@@ -1767,29 +1887,6 @@
   }
 }
 
-class _ImageAnalysisHostApiCodec extends StandardMessageCodec {
-  const _ImageAnalysisHostApiCodec();
-  @override
-  void writeValue(WriteBuffer buffer, Object? value) {
-    if (value is ResolutionInfo) {
-      buffer.putUint8(128);
-      writeValue(buffer, value.encode());
-    } else {
-      super.writeValue(buffer, value);
-    }
-  }
-
-  @override
-  Object? readValueOfType(int type, ReadBuffer buffer) {
-    switch (type) {
-      case 128:
-        return ResolutionInfo.decode(readValue(buffer)!);
-      default:
-        return super.readValueOfType(type, buffer);
-    }
-  }
-}
-
 class ImageAnalysisHostApi {
   /// Constructor for [ImageAnalysisHostApi].  The [binaryMessenger] named argument is
   /// available for dependency injection.  If it is left null, the default
@@ -1798,16 +1895,15 @@
       : _binaryMessenger = binaryMessenger;
   final BinaryMessenger? _binaryMessenger;
 
-  static const MessageCodec<Object?> codec = _ImageAnalysisHostApiCodec();
+  static const MessageCodec<Object?> codec = StandardMessageCodec();
 
-  Future<void> create(int arg_identifier,
-      ResolutionInfo? arg_targetResolutionIdentifier) async {
+  Future<void> create(int arg_identifier, int? arg_resolutionSelectorId) async {
     final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
         'dev.flutter.pigeon.ImageAnalysisHostApi.create', codec,
         binaryMessenger: _binaryMessenger);
-    final List<Object?>? replyList = await channel
-            .send(<Object?>[arg_identifier, arg_targetResolutionIdentifier])
-        as List<Object?>?;
+    final List<Object?>? replyList =
+        await channel.send(<Object?>[arg_identifier, arg_resolutionSelectorId])
+            as List<Object?>?;
     if (replyList == null) {
       throw PlatformException(
         code: 'channel-error',
diff --git a/packages/camera/camera_android_camerax/lib/src/image_analysis.dart b/packages/camera/camera_android_camerax/lib/src/image_analysis.dart
index 4d2a335..e28457c 100644
--- a/packages/camera/camera_android_camerax/lib/src/image_analysis.dart
+++ b/packages/camera/camera_android_camerax/lib/src/image_analysis.dart
@@ -12,6 +12,7 @@
 import 'camerax_library.g.dart';
 import 'instance_manager.dart';
 import 'java_object.dart';
+import 'resolution_selector.dart';
 import 'use_case.dart';
 
 /// Use case for providing CPU accessible images for performing image analysis.
@@ -23,13 +24,13 @@
   ImageAnalysis(
       {BinaryMessenger? binaryMessenger,
       InstanceManager? instanceManager,
-      this.targetResolution})
+      this.resolutionSelector})
       : super.detached(
             binaryMessenger: binaryMessenger,
             instanceManager: instanceManager) {
     _api = _ImageAnalysisHostApiImpl(
         binaryMessenger: binaryMessenger, instanceManager: instanceManager);
-    _api.createfromInstances(this, targetResolution);
+    _api.createfromInstances(this, resolutionSelector);
     AndroidCameraXCameraFlutterApis.instance.ensureSetUp();
   }
 
@@ -37,7 +38,7 @@
   ImageAnalysis.detached(
       {BinaryMessenger? binaryMessenger,
       InstanceManager? instanceManager,
-      this.targetResolution})
+      this.resolutionSelector})
       : super.detached(
             binaryMessenger: binaryMessenger,
             instanceManager: instanceManager) {
@@ -49,7 +50,10 @@
   late final _ImageAnalysisHostApiImpl _api;
 
   /// Target resolution of the camera preview stream.
-  final ResolutionInfo? targetResolution;
+  ///
+  /// If not set, this [UseCase] will default to the behavior described in:
+  /// https://developer.android.com/reference/androidx/camera/core/ImageAnalysis.Builder#setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector).
+  final ResolutionSelector? resolutionSelector;
 
   /// Sets an [Analyzer] to receive and analyze images.
   Future<void> setAnalyzer(Analyzer analyzer) =>
@@ -83,18 +87,20 @@
   /// on the native side.
   Future<void> createfromInstances(
     ImageAnalysis instance,
-    ResolutionInfo? targetResolution,
+    ResolutionSelector? resolutionSelector,
   ) {
     return create(
       instanceManager.addDartCreatedInstance(
         instance,
         onCopy: (ImageAnalysis original) => ImageAnalysis.detached(
-          targetResolution: original.targetResolution,
+          resolutionSelector: original.resolutionSelector,
           binaryMessenger: binaryMessenger,
           instanceManager: instanceManager,
         ),
       ),
-      targetResolution,
+      resolutionSelector == null
+          ? null
+          : instanceManager.getIdentifier(resolutionSelector),
     );
   }
 
diff --git a/packages/camera/camera_android_camerax/lib/src/image_capture.dart b/packages/camera/camera_android_camerax/lib/src/image_capture.dart
index f7f45d1..76fd9c4 100644
--- a/packages/camera/camera_android_camerax/lib/src/image_capture.dart
+++ b/packages/camera/camera_android_camerax/lib/src/image_capture.dart
@@ -8,6 +8,7 @@
 import 'camerax_library.g.dart';
 import 'instance_manager.dart';
 import 'java_object.dart';
+import 'resolution_selector.dart';
 import 'use_case.dart';
 
 /// Use case for picture taking.
@@ -20,14 +21,14 @@
     BinaryMessenger? binaryMessenger,
     InstanceManager? instanceManager,
     this.targetFlashMode,
-    this.targetResolution,
+    this.resolutionSelector,
   }) : super.detached(
           binaryMessenger: binaryMessenger,
           instanceManager: instanceManager,
         ) {
     _api = ImageCaptureHostApiImpl(
         binaryMessenger: binaryMessenger, instanceManager: instanceManager);
-    _api.createFromInstance(this, targetFlashMode, targetResolution);
+    _api.createFromInstance(this, targetFlashMode, resolutionSelector);
   }
 
   /// Constructs a [ImageCapture] that is not automatically attached to a native object.
@@ -35,7 +36,7 @@
     BinaryMessenger? binaryMessenger,
     InstanceManager? instanceManager,
     this.targetFlashMode,
-    this.targetResolution,
+    this.resolutionSelector,
   }) : super.detached(
           binaryMessenger: binaryMessenger,
           instanceManager: instanceManager,
@@ -50,7 +51,10 @@
   final int? targetFlashMode;
 
   /// Target resolution of the image output from taking a picture.
-  final ResolutionInfo? targetResolution;
+  ///
+  /// If not set, this [UseCase] will default to the behavior described in:
+  /// https://developer.android.com/reference/androidx/camera/core/ImageCapture.Builder#setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector).
+  final ResolutionSelector? resolutionSelector;
 
   /// Constant for automatic flash mode.
   ///
@@ -121,16 +125,21 @@
   /// Creates an [ImageCapture] instance with the flash mode and target resolution
   /// if specified.
   void createFromInstance(ImageCapture instance, int? targetFlashMode,
-      ResolutionInfo? targetResolution) {
+      ResolutionSelector? resolutionSelector) {
     final int identifier = instanceManager.addDartCreatedInstance(instance,
         onCopy: (ImageCapture original) {
       return ImageCapture.detached(
           binaryMessenger: binaryMessenger,
           instanceManager: instanceManager,
           targetFlashMode: original.targetFlashMode,
-          targetResolution: original.targetResolution);
+          resolutionSelector: original.resolutionSelector);
     });
-    create(identifier, targetFlashMode, targetResolution);
+    create(
+        identifier,
+        targetFlashMode,
+        resolutionSelector == null
+            ? null
+            : instanceManager.getIdentifier(resolutionSelector));
   }
 
   /// Sets the flash mode for the specified [ImageCapture] instance to take
diff --git a/packages/camera/camera_android_camerax/lib/src/preview.dart b/packages/camera/camera_android_camerax/lib/src/preview.dart
index a530746..f056807 100644
--- a/packages/camera/camera_android_camerax/lib/src/preview.dart
+++ b/packages/camera/camera_android_camerax/lib/src/preview.dart
@@ -8,6 +8,7 @@
 import 'camerax_library.g.dart';
 import 'instance_manager.dart';
 import 'java_object.dart';
+import 'resolution_selector.dart';
 import 'use_case.dart';
 
 /// Use case that provides a camera preview stream for display.
@@ -20,13 +21,13 @@
       {BinaryMessenger? binaryMessenger,
       InstanceManager? instanceManager,
       this.targetRotation,
-      this.targetResolution})
+      this.resolutionSelector})
       : super.detached(
             binaryMessenger: binaryMessenger,
             instanceManager: instanceManager) {
     _api = PreviewHostApiImpl(
         binaryMessenger: binaryMessenger, instanceManager: instanceManager);
-    _api.createFromInstance(this, targetRotation, targetResolution);
+    _api.createFromInstance(this, targetRotation, resolutionSelector);
   }
 
   /// Constructs a [Preview] that is not automatically attached to a native object.
@@ -34,7 +35,7 @@
       {BinaryMessenger? binaryMessenger,
       InstanceManager? instanceManager,
       this.targetRotation,
-      this.targetResolution})
+      this.resolutionSelector})
       : super.detached(
             binaryMessenger: binaryMessenger,
             instanceManager: instanceManager) {
@@ -48,7 +49,10 @@
   final int? targetRotation;
 
   /// Target resolution of the camera preview stream.
-  final ResolutionInfo? targetResolution;
+  ///
+  /// If not set, this [UseCase] will default to the behavior described in:
+  /// https://developer.android.com/reference/androidx/camera/core/Preview.Builder#setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector).
+  final ResolutionSelector? resolutionSelector;
 
   /// Sets the surface provider for the preview stream.
   ///
@@ -92,17 +96,22 @@
 
   /// Creates a [Preview] with the target rotation and target resolution if
   /// specified.
-  void createFromInstance(
-      Preview instance, int? targetRotation, ResolutionInfo? targetResolution) {
+  void createFromInstance(Preview instance, int? targetRotation,
+      ResolutionSelector? resolutionSelector) {
     final int identifier = instanceManager.addDartCreatedInstance(instance,
         onCopy: (Preview original) {
       return Preview.detached(
           binaryMessenger: binaryMessenger,
           instanceManager: instanceManager,
           targetRotation: original.targetRotation,
-          targetResolution: original.targetResolution);
+          resolutionSelector: original.resolutionSelector);
     });
-    create(identifier, targetRotation, targetResolution);
+    create(
+        identifier,
+        targetRotation,
+        resolutionSelector == null
+            ? null
+            : instanceManager.getIdentifier(resolutionSelector));
   }
 
   /// Sets the surface provider of the specified [Preview] instance and returns
diff --git a/packages/camera/camera_android_camerax/lib/src/resolution_selector.dart b/packages/camera/camera_android_camerax/lib/src/resolution_selector.dart
new file mode 100644
index 0000000..7419172
--- /dev/null
+++ b/packages/camera/camera_android_camerax/lib/src/resolution_selector.dart
@@ -0,0 +1,108 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/services.dart';
+import 'package:meta/meta.dart' show immutable;
+
+import 'aspect_ratio_strategy.dart';
+import 'camerax_library.g.dart';
+import 'instance_manager.dart';
+import 'java_object.dart';
+import 'resolution_strategy.dart';
+
+/// A set of requirements and priorities used to select a resolution for a
+/// UseCase.
+///
+/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionSelector.
+@immutable
+class ResolutionSelector extends JavaObject {
+  /// Construct a [ResolutionSelector].
+  ResolutionSelector({
+    this.resolutionStrategy,
+    this.aspectRatioStrategy,
+    super.binaryMessenger,
+    super.instanceManager,
+  })  : _api = _ResolutionSelectorHostApiImpl(
+          instanceManager: instanceManager,
+          binaryMessenger: binaryMessenger,
+        ),
+        super.detached() {
+    _api.createFromInstances(this, resolutionStrategy, aspectRatioStrategy);
+  }
+
+  /// Instantiates a [ResolutionSelector] without creating and attaching to an
+  /// instance of the associated native class.
+  ///
+  /// This should only be used outside of tests by subclasses created by this
+  /// library or to create a copy for an [InstanceManager].
+  ResolutionSelector.detached({
+    this.resolutionStrategy,
+    this.aspectRatioStrategy,
+    super.binaryMessenger,
+    super.instanceManager,
+  })  : _api = _ResolutionSelectorHostApiImpl(
+          instanceManager: instanceManager,
+          binaryMessenger: binaryMessenger,
+        ),
+        super.detached();
+
+  final _ResolutionSelectorHostApiImpl _api;
+
+  /// Determines how the UseCase will choose the resolution of the captured
+  /// image.
+  final ResolutionStrategy? resolutionStrategy;
+
+  /// Determines how the UseCase will choose the aspect ratio of the captured
+  /// image.
+  final AspectRatioStrategy? aspectRatioStrategy;
+}
+
+/// Host API implementation of [ResolutionSelector].
+class _ResolutionSelectorHostApiImpl extends ResolutionSelectorHostApi {
+  /// Constructs an [_ResolutionSelectorHostApiImpl].
+  ///
+  /// If [binaryMessenger] is null, the default [BinaryMessenger] will be used,
+  /// which routes to the host platform.
+  ///
+  /// An [instanceManager] is typically passed when a copy of an instance
+  /// contained by an [InstanceManager] is being created. If left null, it
+  /// will default to the global instance defined in [JavaObject].
+  _ResolutionSelectorHostApiImpl({
+    this.binaryMessenger,
+    InstanceManager? instanceManager,
+  })  : instanceManager = instanceManager ?? JavaObject.globalInstanceManager,
+        super(binaryMessenger: binaryMessenger);
+
+  /// Receives binary data across the Flutter platform barrier.
+  final BinaryMessenger? binaryMessenger;
+
+  /// Maintains instances stored to communicate with native language objects.
+  final InstanceManager instanceManager;
+
+  /// Creates a [ResolutionSelector] on the native side with the
+  /// [ResolutionStrategy] and [AspectRatioStrategy] if specified.
+  Future<void> createFromInstances(
+    ResolutionSelector instance,
+    ResolutionStrategy? resolutionStrategy,
+    AspectRatioStrategy? aspectRatioStrategy,
+  ) {
+    return create(
+      instanceManager.addDartCreatedInstance(
+        instance,
+        onCopy: (ResolutionSelector original) => ResolutionSelector.detached(
+          resolutionStrategy: original.resolutionStrategy,
+          aspectRatioStrategy: original.aspectRatioStrategy,
+          binaryMessenger: binaryMessenger,
+          instanceManager: instanceManager,
+        ),
+      ),
+      resolutionStrategy == null
+          ? null
+          : instanceManager.getIdentifier(resolutionStrategy)!,
+      aspectRatioStrategy == null
+          ? null
+          : instanceManager.getIdentifier(aspectRatioStrategy)!,
+    );
+  }
+}
diff --git a/packages/camera/camera_android_camerax/lib/src/resolution_strategy.dart b/packages/camera/camera_android_camerax/lib/src/resolution_strategy.dart
new file mode 100644
index 0000000..80669f3
--- /dev/null
+++ b/packages/camera/camera_android_camerax/lib/src/resolution_strategy.dart
@@ -0,0 +1,189 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/services.dart';
+import 'package:meta/meta.dart' show immutable;
+
+import 'camerax_library.g.dart';
+import 'instance_manager.dart';
+import 'java_object.dart';
+
+/// The resolution strategy defines the resolution selection sequence to select
+/// the best size.
+///
+/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy.
+@immutable
+class ResolutionStrategy extends JavaObject {
+  /// Constructs a [ResolutionStrategy].
+  ResolutionStrategy({
+    required Size this.boundSize,
+    this.fallbackRule,
+    super.binaryMessenger,
+    super.instanceManager,
+  })  : _api = _ResolutionStrategyHostApiImpl(
+          instanceManager: instanceManager,
+          binaryMessenger: binaryMessenger,
+        ),
+        super.detached() {
+    _api.createFromInstances(this, boundSize, fallbackRule);
+  }
+
+  /// Constructs a [ResolutionStrategy] that represents the strategy that
+  /// chooses the highest available resolution.
+  ///
+  /// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy#HIGHEST_AVAILABLE_STRATEGY().
+  ResolutionStrategy.highestAvailableStrategy({
+    super.binaryMessenger,
+    super.instanceManager,
+  })  : _api = _ResolutionStrategyHostApiImpl(
+          instanceManager: instanceManager,
+          binaryMessenger: binaryMessenger,
+        ),
+        boundSize = null,
+        fallbackRule = null,
+        super.detached() {
+    _api.createFromInstances(this, boundSize, fallbackRule);
+  }
+
+  /// Instantiates a [ResolutionStrategy] without creating and attaching to an
+  /// instance of the associated native class.
+  ///
+  /// This should only be used outside of tests by subclasses created by this
+  /// library or to create a copy for an [InstanceManager].
+  ResolutionStrategy.detached({
+    required this.boundSize,
+    this.fallbackRule,
+    super.binaryMessenger,
+    super.instanceManager,
+  })  : _api = _ResolutionStrategyHostApiImpl(
+          instanceManager: instanceManager,
+          binaryMessenger: binaryMessenger,
+        ),
+        super.detached();
+
+  /// Instantiates a [ResolutionStrategy] that represents the strategy that
+  /// chooses the highest available resolution without creating and attaching to
+  /// an instance of the associated native class.
+  ///
+  /// This should only be used outside of tests by subclasses created by this
+  /// library or to create a copy for an [InstanceManager].
+  ResolutionStrategy.detachedHighestAvailableStrategy({
+    super.binaryMessenger,
+    super.instanceManager,
+  })  : _api = _ResolutionStrategyHostApiImpl(
+          instanceManager: instanceManager,
+          binaryMessenger: binaryMessenger,
+        ),
+        boundSize = null,
+        fallbackRule = null,
+        super.detached();
+
+  /// CameraX doesn't select an alternate size when the specified bound size is
+  /// unavailable.
+  ///
+  /// Applications will receive [PlatformException] when binding the [UseCase]s
+  /// with this fallback rule if the device doesn't support the specified bound
+  /// size.
+  ///
+  /// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy#FALLBACK_RULE_NONE().
+  static const int fallbackRuleNone = 0;
+
+  /// When the specified bound size is unavailable, CameraX falls back to select
+  /// the closest higher resolution size.
+  ///
+  /// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy#FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER().
+  static const int fallbackRuleClosestHigherThenLower = 1;
+
+  /// When the specified bound size is unavailable, CameraX falls back to the
+  /// closest higher resolution size.
+  ///
+  /// If CameraX still cannot find any available resolution, it will fallback to
+  /// select other lower resolutions.
+  ///
+  /// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy#FALLBACK_RULE_CLOSEST_HIGHER().
+  static const int fallbackRuleClosestHigher = 2;
+
+  /// When the specified bound size is unavailable, CameraX falls back to select
+  /// the closest lower resolution size.
+  ///
+  /// If CameraX still cannot find any available resolution, it will fallback to
+  /// select other higher resolutions.
+  ///
+  /// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy#FALLBACK_RULE_CLOSEST_LOWER_THEN_HIGHER().
+  static const int fallbackRuleClosestLowerThenHigher = 3;
+
+  /// When the specified bound size is unavailable, CameraX falls back to the
+  /// closest lower resolution size.
+  ///
+  /// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy#FALLBACK_RULE_CLOSEST_LOWER().
+  static const int fallbackRuleClosestLower = 4;
+
+  final _ResolutionStrategyHostApiImpl _api;
+
+  /// The specified bound size for the desired resolution of the camera.
+  ///
+  /// If left null, [fallbackRule] must also be left null in order to create a
+  /// valid [ResolutionStrategy]. This will create the [ResolutionStrategy]
+  /// that chooses the highest available resolution, which can also be retrieved
+  /// by calling [getHighestAvailableStrategy].
+  final Size? boundSize;
+
+  /// The fallback rule for choosing an alternate size when the specified bound
+  /// size is unavailable.
+  ///
+  /// Must be left null if [boundSize] is specified as null. This will create
+  /// the [ResolutionStrategy] that chooses the highest available resolution,
+  /// which can also be retrieved by calling [getHighestAvailableStrategy].
+  final int? fallbackRule;
+}
+
+/// Host API implementation of [ResolutionStrategy].
+class _ResolutionStrategyHostApiImpl extends ResolutionStrategyHostApi {
+  /// Constructs an [_ResolutionStrategyHostApiImpl].
+  ///
+  /// If [binaryMessenger] is null, the default [BinaryMessenger] will be used,
+  /// which routes to the host platform.
+  ///
+  /// An [instanceManager] is typically passed when a copy of an instance
+  /// contained by an [InstanceManager] is being created. If left null, it
+  /// will default to the global instance defined in [JavaObject].
+  _ResolutionStrategyHostApiImpl({
+    this.binaryMessenger,
+    InstanceManager? instanceManager,
+  })  : instanceManager = instanceManager ?? JavaObject.globalInstanceManager,
+        super(binaryMessenger: binaryMessenger);
+
+  /// Receives binary data across the Flutter platform barrier.
+  final BinaryMessenger? binaryMessenger;
+
+  /// Maintains instances stored to communicate with native language objects.
+  final InstanceManager instanceManager;
+
+  /// Creates a [ResolutionStrategy] on the native side with the bound [Size]
+  /// and fallback rule, if specified.
+  Future<void> createFromInstances(
+    ResolutionStrategy instance,
+    Size? boundSize,
+    int? fallbackRule,
+  ) {
+    return create(
+      instanceManager.addDartCreatedInstance(
+        instance,
+        onCopy: (ResolutionStrategy original) => ResolutionStrategy.detached(
+          boundSize: original.boundSize,
+          fallbackRule: original.fallbackRule,
+          binaryMessenger: binaryMessenger,
+          instanceManager: instanceManager,
+        ),
+      ),
+      boundSize == null
+          ? null
+          : ResolutionInfo(
+              width: boundSize.width.toInt(),
+              height: boundSize.height.toInt(),
+            ),
+      fallbackRule,
+    );
+  }
+}
diff --git a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart
index 601601d..a22d7f6 100644
--- a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart
+++ b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart
@@ -196,7 +196,7 @@
 
 @HostApi(dartHostTestHandler: 'TestPreviewHostApi')
 abstract class PreviewHostApi {
-  void create(int identifier, int? rotation, ResolutionInfo? targetResolution);
+  void create(int identifier, int? rotation, int? resolutionSelectorId);
 
   int setSurfaceProvider(int identifier);
 
@@ -261,7 +261,7 @@
 
 @HostApi(dartHostTestHandler: 'TestImageCaptureHostApi')
 abstract class ImageCaptureHostApi {
-  void create(int identifier, int? flashMode, ResolutionInfo? targetResolution);
+  void create(int identifier, int? flashMode, int? resolutionSelectorId);
 
   void setFlashMode(int identifier, int flashMode);
 
@@ -269,6 +269,25 @@
   String takePicture(int identifier);
 }
 
+@HostApi(dartHostTestHandler: 'TestResolutionStrategyHostApi')
+abstract class ResolutionStrategyHostApi {
+  void create(int identifier, ResolutionInfo? boundSize, int? fallbackRule);
+}
+
+@HostApi(dartHostTestHandler: 'TestResolutionSelectorHostApi')
+abstract class ResolutionSelectorHostApi {
+  void create(
+    int identifier,
+    int? resolutionStrategyIdentifier,
+    int? aspectRatioStrategyIdentifier,
+  );
+}
+
+@HostApi(dartHostTestHandler: 'TestAspectRatioStrategyHostApi')
+abstract class AspectRatioStrategyHostApi {
+  void create(int identifier, int preferredAspectRatio, int fallbackRule);
+}
+
 @FlutterApi()
 abstract class CameraStateFlutterApi {
   void create(int identifier, CameraStateTypeData type, int? errorIdentifier);
@@ -289,7 +308,7 @@
 
 @HostApi(dartHostTestHandler: 'TestImageAnalysisHostApi')
 abstract class ImageAnalysisHostApi {
-  void create(int identifier, ResolutionInfo? targetResolutionIdentifier);
+  void create(int identifier, int? resolutionSelectorId);
 
   void setAnalyzer(int identifier, int analyzerIdentifier);
 
diff --git a/packages/camera/camera_android_camerax/pubspec.yaml b/packages/camera/camera_android_camerax/pubspec.yaml
index 0fea9fc..f8927d0 100644
--- a/packages/camera/camera_android_camerax/pubspec.yaml
+++ b/packages/camera/camera_android_camerax/pubspec.yaml
@@ -2,7 +2,7 @@
 description: Android implementation of the camera plugin using the CameraX library.
 repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
-version: 0.5.0+11
+version: 0.5.0+12
 
 environment:
   sdk: ">=2.19.0 <4.0.0"
diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart
index bdebdce..a0e60b6 100644
--- a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart
+++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart
@@ -1127,13 +1127,12 @@
   }
 
   @override
-  Preview createPreview(int targetRotation, ResolutionInfo? targetResolution) {
+  Preview createPreview(int targetRotation) {
     return testPreview;
   }
 
   @override
-  ImageCapture createImageCapture(
-      int? flashMode, ResolutionInfo? targetResolution) {
+  ImageCapture createImageCapture(int? flashMode) {
     return testImageCapture;
   }
 
@@ -1148,7 +1147,7 @@
   }
 
   @override
-  ImageAnalysis createImageAnalysis(ResolutionInfo? targetResolution) {
+  ImageAnalysis createImageAnalysis() {
     return mockImageAnalysis;
   }
 }
diff --git a/packages/camera/camera_android_camerax/test/aspect_ratio_strategy_test.dart b/packages/camera/camera_android_camerax/test/aspect_ratio_strategy_test.dart
new file mode 100644
index 0000000..28ec032
--- /dev/null
+++ b/packages/camera/camera_android_camerax/test/aspect_ratio_strategy_test.dart
@@ -0,0 +1,84 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:camera_android_camerax/src/aspect_ratio_strategy.dart';
+import 'package:camera_android_camerax/src/instance_manager.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:mockito/annotations.dart';
+import 'package:mockito/mockito.dart';
+
+import 'aspect_ratio_strategy_test.mocks.dart';
+import 'test_camerax_library.g.dart';
+
+@GenerateMocks(<Type>[
+  TestAspectRatioStrategyHostApi,
+  TestInstanceManagerHostApi,
+])
+void main() {
+  TestWidgetsFlutterBinding.ensureInitialized();
+
+  group('AspectRatioStrategy', () {
+    tearDown(() {
+      TestAspectRatioStrategyHostApi.setup(null);
+      TestInstanceManagerHostApi.setup(null);
+    });
+
+    test(
+        'detached create does not make call to create expected AspectRatioStrategy instance',
+        () async {
+      final MockTestAspectRatioStrategyHostApi mockApi =
+          MockTestAspectRatioStrategyHostApi();
+      TestAspectRatioStrategyHostApi.setup(mockApi);
+
+      final InstanceManager instanceManager = InstanceManager(
+        onWeakReferenceRemoved: (_) {},
+      );
+
+      const int preferredAspectRatio = 1;
+
+      const int fallbackRule = 1;
+
+      AspectRatioStrategy.detached(
+        preferredAspectRatio: preferredAspectRatio,
+        fallbackRule: fallbackRule,
+        instanceManager: instanceManager,
+      );
+
+      verifyNever(mockApi.create(
+        argThat(isA<int>()),
+        preferredAspectRatio,
+        fallbackRule,
+      ));
+    });
+
+    test(
+        'HostApi create makes call to create expected AspectRatioStrategy instance',
+        () {
+      final MockTestAspectRatioStrategyHostApi mockApi =
+          MockTestAspectRatioStrategyHostApi();
+      TestAspectRatioStrategyHostApi.setup(mockApi);
+      TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
+
+      final InstanceManager instanceManager = InstanceManager(
+        onWeakReferenceRemoved: (_) {},
+      );
+
+      const int preferredAspectRatio = 0;
+
+      const int fallbackRule = 0;
+
+      final AspectRatioStrategy instance = AspectRatioStrategy(
+        preferredAspectRatio: preferredAspectRatio,
+        fallbackRule: fallbackRule,
+        instanceManager: instanceManager,
+      );
+
+      verify(mockApi.create(
+        instanceManager.getIdentifier(instance),
+        preferredAspectRatio,
+        fallbackRule,
+      ));
+    });
+  });
+}
diff --git a/packages/camera/camera_android_camerax/test/aspect_ratio_strategy_test.mocks.dart b/packages/camera/camera_android_camerax/test/aspect_ratio_strategy_test.mocks.dart
new file mode 100644
index 0000000..28dda66
--- /dev/null
+++ b/packages/camera/camera_android_camerax/test/aspect_ratio_strategy_test.mocks.dart
@@ -0,0 +1,68 @@
+// Mocks generated by Mockito 5.4.1 from annotations
+// in camera_android_camerax/test/aspect_ratio_strategy_test.dart.
+// Do not manually edit this file.
+
+// @dart=2.19
+
+// ignore_for_file: no_leading_underscores_for_library_prefixes
+import 'package:mockito/mockito.dart' as _i1;
+
+import 'test_camerax_library.g.dart' as _i2;
+
+// ignore_for_file: type=lint
+// ignore_for_file: avoid_redundant_argument_values
+// ignore_for_file: avoid_setters_without_getters
+// ignore_for_file: comment_references
+// ignore_for_file: implementation_imports
+// ignore_for_file: invalid_use_of_visible_for_testing_member
+// ignore_for_file: prefer_const_constructors
+// ignore_for_file: unnecessary_parenthesis
+// ignore_for_file: camel_case_types
+// ignore_for_file: subtype_of_sealed_class
+
+/// A class which mocks [TestAspectRatioStrategyHostApi].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockTestAspectRatioStrategyHostApi extends _i1.Mock
+    implements _i2.TestAspectRatioStrategyHostApi {
+  MockTestAspectRatioStrategyHostApi() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  void create(
+    int? identifier,
+    int? preferredAspectRatio,
+    int? fallbackRule,
+  ) =>
+      super.noSuchMethod(
+        Invocation.method(
+          #create,
+          [
+            identifier,
+            preferredAspectRatio,
+            fallbackRule,
+          ],
+        ),
+        returnValueForMissingStub: null,
+      );
+}
+
+/// A class which mocks [TestInstanceManagerHostApi].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockTestInstanceManagerHostApi extends _i1.Mock
+    implements _i2.TestInstanceManagerHostApi {
+  MockTestInstanceManagerHostApi() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  void clear() => super.noSuchMethod(
+        Invocation.method(
+          #clear,
+          [],
+        ),
+        returnValueForMissingStub: null,
+      );
+}
diff --git a/packages/camera/camera_android_camerax/test/image_analysis_test.dart b/packages/camera/camera_android_camerax/test/image_analysis_test.dart
index d9c657e..80acd65 100644
--- a/packages/camera/camera_android_camerax/test/image_analysis_test.dart
+++ b/packages/camera/camera_android_camerax/test/image_analysis_test.dart
@@ -3,10 +3,10 @@
 // found in the LICENSE file.
 
 import 'package:camera_android_camerax/src/analyzer.dart';
-import 'package:camera_android_camerax/src/camerax_library.g.dart';
 import 'package:camera_android_camerax/src/image_analysis.dart';
 import 'package:camera_android_camerax/src/image_proxy.dart';
 import 'package:camera_android_camerax/src/instance_manager.dart';
+import 'package:camera_android_camerax/src/resolution_selector.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:mockito/annotations.dart';
 import 'package:mockito/mockito.dart';
@@ -14,7 +14,11 @@
 import 'image_analysis_test.mocks.dart';
 import 'test_camerax_library.g.dart';
 
-@GenerateMocks(<Type>[TestImageAnalysisHostApi, TestInstanceManagerHostApi])
+@GenerateMocks(<Type>[
+  TestImageAnalysisHostApi,
+  TestInstanceManagerHostApi,
+  ResolutionSelector,
+])
 void main() {
   TestWidgetsFlutterBinding.ensureInitialized();
 
@@ -22,13 +26,11 @@
   TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
 
   group('ImageAnalysis', () {
-    setUp(() {});
-
     tearDown(() {
       TestImageAnalysisHostApi.setup(null);
     });
 
-    test('HostApi create', () {
+    test('create calls create on the Java side', () {
       final MockTestImageAnalysisHostApi mockApi =
           MockTestImageAnalysisHostApi();
       TestImageAnalysisHostApi.setup(mockApi);
@@ -37,25 +39,28 @@
         onWeakReferenceRemoved: (_) {},
       );
 
-      const int targetResolutionWidth = 65;
-      const int targetResolutionHeight = 99;
-      final ResolutionInfo targetResolution =
-          ResolutionInfo(width: 65, height: 99);
+      final MockResolutionSelector mockResolutionSelector =
+          MockResolutionSelector();
+      const int mockResolutionSelectorId = 24;
+
+      instanceManager.addHostCreatedInstance(
+          mockResolutionSelector, mockResolutionSelectorId,
+          onCopy: (ResolutionSelector original) {
+        return MockResolutionSelector();
+      });
+
       final ImageAnalysis instance = ImageAnalysis(
-        targetResolution: targetResolution,
+        resolutionSelector: mockResolutionSelector,
         instanceManager: instanceManager,
       );
 
-      final VerificationResult createVerification = verify(mockApi.create(
+      verify(mockApi.create(
           argThat(equals(instanceManager.getIdentifier(instance))),
-          captureAny));
-      final ResolutionInfo capturedResolutionInfo =
-          createVerification.captured.single as ResolutionInfo;
-      expect(capturedResolutionInfo.width, equals(targetResolutionWidth));
-      expect(capturedResolutionInfo.height, equals(targetResolutionHeight));
+          argThat(equals(mockResolutionSelectorId))));
     });
 
-    test('setAnalyzer', () async {
+    test('setAnalyzer makes call to set analyzer on ImageAnalysis instance',
+        () async {
       final MockTestImageAnalysisHostApi mockApi =
           MockTestImageAnalysisHostApi();
       TestImageAnalysisHostApi.setup(mockApi);
@@ -65,7 +70,7 @@
       );
 
       final ImageAnalysis instance = ImageAnalysis.detached(
-        targetResolution: ResolutionInfo(width: 75, height: 98),
+        resolutionSelector: MockResolutionSelector(),
         instanceManager: instanceManager,
       );
       const int instanceIdentifier = 0;
@@ -73,7 +78,7 @@
         instance,
         instanceIdentifier,
         onCopy: (ImageAnalysis original) => ImageAnalysis.detached(
-          targetResolution: original.targetResolution,
+          resolutionSelector: original.resolutionSelector,
           instanceManager: instanceManager,
         ),
       );
@@ -102,7 +107,8 @@
       ));
     });
 
-    test('clearAnalyzer', () async {
+    test('clearAnalyzer makes call to clear analyzer on ImageAnalysis instance',
+        () async {
       final MockTestImageAnalysisHostApi mockApi =
           MockTestImageAnalysisHostApi();
       TestImageAnalysisHostApi.setup(mockApi);
@@ -112,7 +118,7 @@
       );
 
       final ImageAnalysis instance = ImageAnalysis.detached(
-        targetResolution: ResolutionInfo(width: 75, height: 98),
+        resolutionSelector: MockResolutionSelector(),
         instanceManager: instanceManager,
       );
       const int instanceIdentifier = 0;
@@ -120,7 +126,7 @@
         instance,
         instanceIdentifier,
         onCopy: (ImageAnalysis original) => ImageAnalysis.detached(
-          targetResolution: original.targetResolution,
+          resolutionSelector: original.resolutionSelector,
           instanceManager: instanceManager,
         ),
       );
diff --git a/packages/camera/camera_android_camerax/test/image_analysis_test.mocks.dart b/packages/camera/camera_android_camerax/test/image_analysis_test.mocks.dart
index cbece72..b0df579 100644
--- a/packages/camera/camera_android_camerax/test/image_analysis_test.mocks.dart
+++ b/packages/camera/camera_android_camerax/test/image_analysis_test.mocks.dart
@@ -5,7 +5,7 @@
 // @dart=2.19
 
 // ignore_for_file: no_leading_underscores_for_library_prefixes
-import 'package:camera_android_camerax/src/camerax_library.g.dart' as _i3;
+import 'package:camera_android_camerax/src/resolution_selector.dart' as _i3;
 import 'package:mockito/mockito.dart' as _i1;
 
 import 'test_camerax_library.g.dart' as _i2;
@@ -33,14 +33,14 @@
   @override
   void create(
     int? identifier,
-    _i3.ResolutionInfo? targetResolutionIdentifier,
+    int? resolutionSelectorId,
   ) =>
       super.noSuchMethod(
         Invocation.method(
           #create,
           [
             identifier,
-            targetResolutionIdentifier,
+            resolutionSelectorId,
           ],
         ),
         returnValueForMissingStub: null,
@@ -88,3 +88,14 @@
         returnValueForMissingStub: null,
       );
 }
+
+/// A class which mocks [ResolutionSelector].
+///
+/// See the documentation for Mockito's code generation for more information.
+// ignore: must_be_immutable
+class MockResolutionSelector extends _i1.Mock
+    implements _i3.ResolutionSelector {
+  MockResolutionSelector() {
+    _i1.throwOnMissingStub(this);
+  }
+}
diff --git a/packages/camera/camera_android_camerax/test/image_capture_test.dart b/packages/camera/camera_android_camerax/test/image_capture_test.dart
index 21c0719..c50314e 100644
--- a/packages/camera/camera_android_camerax/test/image_capture_test.dart
+++ b/packages/camera/camera_android_camerax/test/image_capture_test.dart
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:camera_android_camerax/src/camerax_library.g.dart';
 import 'package:camera_android_camerax/src/image_capture.dart';
 import 'package:camera_android_camerax/src/instance_manager.dart';
+import 'package:camera_android_camerax/src/resolution_selector.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:mockito/annotations.dart';
 import 'package:mockito/mockito.dart';
@@ -12,7 +12,11 @@
 import 'image_capture_test.mocks.dart';
 import 'test_camerax_library.g.dart';
 
-@GenerateMocks(<Type>[TestImageCaptureHostApi, TestInstanceManagerHostApi])
+@GenerateMocks(<Type>[
+  TestImageCaptureHostApi,
+  TestInstanceManagerHostApi,
+  ResolutionSelector
+])
 void main() {
   TestWidgetsFlutterBinding.ensureInitialized();
 
@@ -32,11 +36,11 @@
       ImageCapture.detached(
         instanceManager: instanceManager,
         targetFlashMode: ImageCapture.flashModeOn,
-        targetResolution: ResolutionInfo(width: 50, height: 10),
+        resolutionSelector: MockResolutionSelector(),
       );
 
       verifyNever(mockApi.create(argThat(isA<int>()), argThat(isA<int>()),
-          argThat(isA<ResolutionInfo>())));
+          argThat(isA<ResolutionSelector>())));
     });
 
     test('create calls create on the Java side', () async {
@@ -47,21 +51,26 @@
         onWeakReferenceRemoved: (_) {},
       );
       const int targetFlashMode = ImageCapture.flashModeAuto;
-      const int targetResolutionWidth = 10;
-      const int targetResolutionHeight = 50;
+      final MockResolutionSelector mockResolutionSelector =
+          MockResolutionSelector();
+      const int mockResolutionSelectorId = 24;
+
+      instanceManager.addHostCreatedInstance(
+          mockResolutionSelector, mockResolutionSelectorId,
+          onCopy: (ResolutionSelector original) {
+        return MockResolutionSelector();
+      });
+
       ImageCapture(
         instanceManager: instanceManager,
         targetFlashMode: targetFlashMode,
-        targetResolution: ResolutionInfo(
-            width: targetResolutionWidth, height: targetResolutionHeight),
+        resolutionSelector: mockResolutionSelector,
       );
 
-      final VerificationResult createVerification = verify(mockApi.create(
-          argThat(isA<int>()), argThat(equals(targetFlashMode)), captureAny));
-      final ResolutionInfo capturedResolutionInfo =
-          createVerification.captured.single as ResolutionInfo;
-      expect(capturedResolutionInfo.width, equals(targetResolutionWidth));
-      expect(capturedResolutionInfo.height, equals(targetResolutionHeight));
+      verify(mockApi.create(
+          argThat(isA<int>()),
+          argThat(equals(targetFlashMode)),
+          argThat(equals(mockResolutionSelectorId))));
     });
 
     test('setFlashMode makes call to set flash mode for ImageCapture instance',
diff --git a/packages/camera/camera_android_camerax/test/image_capture_test.mocks.dart b/packages/camera/camera_android_camerax/test/image_capture_test.mocks.dart
index 1b9e1e7..44331c9 100644
--- a/packages/camera/camera_android_camerax/test/image_capture_test.mocks.dart
+++ b/packages/camera/camera_android_camerax/test/image_capture_test.mocks.dart
@@ -5,9 +5,9 @@
 // @dart=2.19
 
 // ignore_for_file: no_leading_underscores_for_library_prefixes
-import 'dart:async' as _i4;
+import 'dart:async' as _i3;
 
-import 'package:camera_android_camerax/src/camerax_library.g.dart' as _i3;
+import 'package:camera_android_camerax/src/resolution_selector.dart' as _i4;
 import 'package:mockito/mockito.dart' as _i1;
 
 import 'test_camerax_library.g.dart' as _i2;
@@ -36,7 +36,7 @@
   void create(
     int? identifier,
     int? flashMode,
-    _i3.ResolutionInfo? targetResolution,
+    int? resolutionSelectorId,
   ) =>
       super.noSuchMethod(
         Invocation.method(
@@ -44,7 +44,7 @@
           [
             identifier,
             flashMode,
-            targetResolution,
+            resolutionSelectorId,
           ],
         ),
         returnValueForMissingStub: null,
@@ -65,13 +65,13 @@
         returnValueForMissingStub: null,
       );
   @override
-  _i4.Future<String> takePicture(int? identifier) => (super.noSuchMethod(
+  _i3.Future<String> takePicture(int? identifier) => (super.noSuchMethod(
         Invocation.method(
           #takePicture,
           [identifier],
         ),
-        returnValue: _i4.Future<String>.value(''),
-      ) as _i4.Future<String>);
+        returnValue: _i3.Future<String>.value(''),
+      ) as _i3.Future<String>);
 }
 
 /// A class which mocks [TestInstanceManagerHostApi].
@@ -92,3 +92,14 @@
         returnValueForMissingStub: null,
       );
 }
+
+/// A class which mocks [ResolutionSelector].
+///
+/// See the documentation for Mockito's code generation for more information.
+// ignore: must_be_immutable
+class MockResolutionSelector extends _i1.Mock
+    implements _i4.ResolutionSelector {
+  MockResolutionSelector() {
+    _i1.throwOnMissingStub(this);
+  }
+}
diff --git a/packages/camera/camera_android_camerax/test/preview_test.dart b/packages/camera/camera_android_camerax/test/preview_test.dart
index 6eacd42..29f862c 100644
--- a/packages/camera/camera_android_camerax/test/preview_test.dart
+++ b/packages/camera/camera_android_camerax/test/preview_test.dart
@@ -5,6 +5,7 @@
 import 'package:camera_android_camerax/src/camerax_library.g.dart';
 import 'package:camera_android_camerax/src/instance_manager.dart';
 import 'package:camera_android_camerax/src/preview.dart';
+import 'package:camera_android_camerax/src/resolution_selector.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:mockito/annotations.dart';
 import 'package:mockito/mockito.dart';
@@ -12,7 +13,8 @@
 import 'preview_test.mocks.dart';
 import 'test_camerax_library.g.dart';
 
-@GenerateMocks(<Type>[TestInstanceManagerHostApi, TestPreviewHostApi])
+@GenerateMocks(
+    <Type>[TestInstanceManagerHostApi, TestPreviewHostApi, ResolutionSelector])
 void main() {
   TestWidgetsFlutterBinding.ensureInitialized();
 
@@ -32,11 +34,11 @@
       Preview.detached(
         instanceManager: instanceManager,
         targetRotation: 90,
-        targetResolution: ResolutionInfo(width: 50, height: 10),
+        resolutionSelector: MockResolutionSelector(),
       );
 
       verifyNever(mockApi.create(argThat(isA<int>()), argThat(isA<int>()),
-          argThat(isA<ResolutionInfo>())));
+          argThat(isA<ResolutionSelector>())));
     });
 
     test('create calls create on the Java side', () async {
@@ -47,21 +49,26 @@
         onWeakReferenceRemoved: (_) {},
       );
       const int targetRotation = 90;
-      const int targetResolutionWidth = 10;
-      const int targetResolutionHeight = 50;
+      final MockResolutionSelector mockResolutionSelector =
+          MockResolutionSelector();
+      const int mockResolutionSelectorId = 24;
+
+      instanceManager.addHostCreatedInstance(
+          mockResolutionSelector, mockResolutionSelectorId,
+          onCopy: (ResolutionSelector original) {
+        return MockResolutionSelector();
+      });
+
       Preview(
         instanceManager: instanceManager,
         targetRotation: targetRotation,
-        targetResolution: ResolutionInfo(
-            width: targetResolutionWidth, height: targetResolutionHeight),
+        resolutionSelector: mockResolutionSelector,
       );
 
-      final VerificationResult createVerification = verify(mockApi.create(
-          argThat(isA<int>()), argThat(equals(targetRotation)), captureAny));
-      final ResolutionInfo capturedResolutionInfo =
-          createVerification.captured.single as ResolutionInfo;
-      expect(capturedResolutionInfo.width, equals(targetResolutionWidth));
-      expect(capturedResolutionInfo.height, equals(targetResolutionHeight));
+      verify(mockApi.create(
+          argThat(isA<int>()),
+          argThat(equals(targetRotation)),
+          argThat(equals(mockResolutionSelectorId))));
     });
 
     test(
diff --git a/packages/camera/camera_android_camerax/test/preview_test.mocks.dart b/packages/camera/camera_android_camerax/test/preview_test.mocks.dart
index ae37836..d56e682 100644
--- a/packages/camera/camera_android_camerax/test/preview_test.mocks.dart
+++ b/packages/camera/camera_android_camerax/test/preview_test.mocks.dart
@@ -6,6 +6,7 @@
 
 // ignore_for_file: no_leading_underscores_for_library_prefixes
 import 'package:camera_android_camerax/src/camerax_library.g.dart' as _i2;
+import 'package:camera_android_camerax/src/resolution_selector.dart' as _i4;
 import 'package:mockito/mockito.dart' as _i1;
 
 import 'test_camerax_library.g.dart' as _i3;
@@ -64,7 +65,7 @@
   void create(
     int? identifier,
     int? rotation,
-    _i2.ResolutionInfo? targetResolution,
+    int? resolutionSelectorId,
   ) =>
       super.noSuchMethod(
         Invocation.method(
@@ -72,7 +73,7 @@
           [
             identifier,
             rotation,
-            targetResolution,
+            resolutionSelectorId,
           ],
         ),
         returnValueForMissingStub: null,
@@ -108,3 +109,14 @@
         ),
       ) as _i2.ResolutionInfo);
 }
+
+/// A class which mocks [ResolutionSelector].
+///
+/// See the documentation for Mockito's code generation for more information.
+// ignore: must_be_immutable
+class MockResolutionSelector extends _i1.Mock
+    implements _i4.ResolutionSelector {
+  MockResolutionSelector() {
+    _i1.throwOnMissingStub(this);
+  }
+}
diff --git a/packages/camera/camera_android_camerax/test/resolution_selector_test.dart b/packages/camera/camera_android_camerax/test/resolution_selector_test.dart
new file mode 100644
index 0000000..45ecef5
--- /dev/null
+++ b/packages/camera/camera_android_camerax/test/resolution_selector_test.dart
@@ -0,0 +1,124 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:ui';
+
+import 'package:camera_android_camerax/src/aspect_ratio_strategy.dart';
+import 'package:camera_android_camerax/src/instance_manager.dart';
+import 'package:camera_android_camerax/src/resolution_selector.dart';
+import 'package:camera_android_camerax/src/resolution_strategy.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:mockito/annotations.dart';
+import 'package:mockito/mockito.dart';
+
+import 'resolution_selector_test.mocks.dart';
+import 'test_camerax_library.g.dart';
+
+@GenerateMocks(<Type>[
+  AspectRatioStrategy,
+  ResolutionStrategy,
+  TestResolutionSelectorHostApi,
+  TestInstanceManagerHostApi,
+])
+void main() {
+  TestWidgetsFlutterBinding.ensureInitialized();
+
+  group('ResolutionSelector', () {
+    tearDown(() {
+      TestResolutionSelectorHostApi.setup(null);
+      TestInstanceManagerHostApi.setup(null);
+    });
+
+    test(
+        'detached constructor does not make call to create expected AspectRatioStrategy instance',
+        () async {
+      final MockTestResolutionSelectorHostApi mockApi =
+          MockTestResolutionSelectorHostApi();
+      TestResolutionSelectorHostApi.setup(mockApi);
+      TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
+
+      final InstanceManager instanceManager = InstanceManager(
+        onWeakReferenceRemoved: (_) {},
+      );
+
+      const int preferredAspectRatio = 1;
+
+      const int fallbackRule = 1;
+
+      AspectRatioStrategy.detached(
+        preferredAspectRatio: preferredAspectRatio,
+        fallbackRule: fallbackRule,
+        instanceManager: instanceManager,
+      );
+
+      ResolutionSelector.detached(
+        resolutionStrategy: MockResolutionStrategy(),
+        aspectRatioStrategy: MockAspectRatioStrategy(),
+        instanceManager: instanceManager,
+      );
+
+      verifyNever(mockApi.create(
+        argThat(isA<int>()),
+        argThat(isA<int>()),
+        argThat(isA<int>()),
+      ));
+    });
+
+    test('HostApi create creates expected ResolutionSelector instance', () {
+      final MockTestResolutionSelectorHostApi mockApi =
+          MockTestResolutionSelectorHostApi();
+      TestResolutionSelectorHostApi.setup(mockApi);
+      TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
+
+      final InstanceManager instanceManager = InstanceManager(
+        onWeakReferenceRemoved: (_) {},
+      );
+
+      final ResolutionStrategy resolutionStrategy = ResolutionStrategy.detached(
+        boundSize: const Size(50, 30),
+        fallbackRule: ResolutionStrategy.fallbackRuleClosestLower,
+        instanceManager: instanceManager,
+      );
+      const int resolutionStrategyIdentifier = 14;
+      instanceManager.addHostCreatedInstance(
+        resolutionStrategy,
+        resolutionStrategyIdentifier,
+        onCopy: (ResolutionStrategy original) => ResolutionStrategy.detached(
+          boundSize: original.boundSize,
+          fallbackRule: original.fallbackRule,
+          instanceManager: instanceManager,
+        ),
+      );
+
+      final AspectRatioStrategy aspectRatioStrategy =
+          AspectRatioStrategy.detached(
+        preferredAspectRatio: AspectRatio.ratio4To3,
+        fallbackRule: AspectRatioStrategy.fallbackRuleAuto,
+        instanceManager: instanceManager,
+      );
+      const int aspectRatioStrategyIdentifier = 15;
+      instanceManager.addHostCreatedInstance(
+        aspectRatioStrategy,
+        aspectRatioStrategyIdentifier,
+        onCopy: (AspectRatioStrategy original) => AspectRatioStrategy.detached(
+          preferredAspectRatio: original.preferredAspectRatio,
+          fallbackRule: original.fallbackRule,
+          instanceManager: instanceManager,
+        ),
+      );
+
+      final ResolutionSelector instance = ResolutionSelector(
+        resolutionStrategy: resolutionStrategy,
+        aspectRatioStrategy: aspectRatioStrategy,
+        instanceManager: instanceManager,
+      );
+
+      verify(mockApi.create(
+        instanceManager.getIdentifier(instance),
+        resolutionStrategyIdentifier,
+        aspectRatioStrategyIdentifier,
+      ));
+    });
+  });
+}
diff --git a/packages/camera/camera_android_camerax/test/resolution_selector_test.mocks.dart b/packages/camera/camera_android_camerax/test/resolution_selector_test.mocks.dart
new file mode 100644
index 0000000..6ab8de8
--- /dev/null
+++ b/packages/camera/camera_android_camerax/test/resolution_selector_test.mocks.dart
@@ -0,0 +1,103 @@
+// Mocks generated by Mockito 5.4.1 from annotations
+// in camera_android_camerax/test/resolution_selector_test.dart.
+// Do not manually edit this file.
+
+// @dart=2.19
+
+// ignore_for_file: no_leading_underscores_for_library_prefixes
+import 'package:camera_android_camerax/src/aspect_ratio_strategy.dart' as _i2;
+import 'package:camera_android_camerax/src/resolution_strategy.dart' as _i3;
+import 'package:mockito/mockito.dart' as _i1;
+
+import 'test_camerax_library.g.dart' as _i4;
+
+// ignore_for_file: type=lint
+// ignore_for_file: avoid_redundant_argument_values
+// ignore_for_file: avoid_setters_without_getters
+// ignore_for_file: comment_references
+// ignore_for_file: implementation_imports
+// ignore_for_file: invalid_use_of_visible_for_testing_member
+// ignore_for_file: prefer_const_constructors
+// ignore_for_file: unnecessary_parenthesis
+// ignore_for_file: camel_case_types
+// ignore_for_file: subtype_of_sealed_class
+
+/// A class which mocks [AspectRatioStrategy].
+///
+/// See the documentation for Mockito's code generation for more information.
+// ignore: must_be_immutable
+class MockAspectRatioStrategy extends _i1.Mock
+    implements _i2.AspectRatioStrategy {
+  MockAspectRatioStrategy() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  int get preferredAspectRatio => (super.noSuchMethod(
+        Invocation.getter(#preferredAspectRatio),
+        returnValue: 0,
+      ) as int);
+  @override
+  int get fallbackRule => (super.noSuchMethod(
+        Invocation.getter(#fallbackRule),
+        returnValue: 0,
+      ) as int);
+}
+
+/// A class which mocks [ResolutionStrategy].
+///
+/// See the documentation for Mockito's code generation for more information.
+// ignore: must_be_immutable
+class MockResolutionStrategy extends _i1.Mock
+    implements _i3.ResolutionStrategy {
+  MockResolutionStrategy() {
+    _i1.throwOnMissingStub(this);
+  }
+}
+
+/// A class which mocks [TestResolutionSelectorHostApi].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockTestResolutionSelectorHostApi extends _i1.Mock
+    implements _i4.TestResolutionSelectorHostApi {
+  MockTestResolutionSelectorHostApi() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  void create(
+    int? identifier,
+    int? resolutionStrategyIdentifier,
+    int? aspectRatioStrategyIdentifier,
+  ) =>
+      super.noSuchMethod(
+        Invocation.method(
+          #create,
+          [
+            identifier,
+            resolutionStrategyIdentifier,
+            aspectRatioStrategyIdentifier,
+          ],
+        ),
+        returnValueForMissingStub: null,
+      );
+}
+
+/// A class which mocks [TestInstanceManagerHostApi].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockTestInstanceManagerHostApi extends _i1.Mock
+    implements _i4.TestInstanceManagerHostApi {
+  MockTestInstanceManagerHostApi() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  void clear() => super.noSuchMethod(
+        Invocation.method(
+          #clear,
+          [],
+        ),
+        returnValueForMissingStub: null,
+      );
+}
diff --git a/packages/camera/camera_android_camerax/test/resolution_strategy_test.dart b/packages/camera/camera_android_camerax/test/resolution_strategy_test.dart
new file mode 100644
index 0000000..9c098b9
--- /dev/null
+++ b/packages/camera/camera_android_camerax/test/resolution_strategy_test.dart
@@ -0,0 +1,109 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:ui';
+
+import 'package:camera_android_camerax/src/camerax_library.g.dart';
+import 'package:camera_android_camerax/src/instance_manager.dart';
+import 'package:camera_android_camerax/src/resolution_strategy.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:mockito/annotations.dart';
+import 'package:mockito/mockito.dart';
+
+import 'resolution_strategy_test.mocks.dart';
+import 'test_camerax_library.g.dart';
+
+@GenerateMocks(<Type>[
+  TestResolutionStrategyHostApi,
+  TestInstanceManagerHostApi,
+])
+void main() {
+  TestWidgetsFlutterBinding.ensureInitialized();
+
+  group('ResolutionStrategy', () {
+    tearDown(() {
+      TestResolutionStrategyHostApi.setup(null);
+      TestInstanceManagerHostApi.setup(null);
+    });
+
+    test(
+        'detached resolutionStrategy constructors do not make call to Host API create',
+        () {
+      final MockTestResolutionStrategyHostApi mockApi =
+          MockTestResolutionStrategyHostApi();
+      TestResolutionStrategyHostApi.setup(mockApi);
+      TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
+
+      final InstanceManager instanceManager = InstanceManager(
+        onWeakReferenceRemoved: (_) {},
+      );
+
+      const Size boundSize = Size(70, 20);
+      const int fallbackRule = 1;
+
+      ResolutionStrategy.detached(
+        boundSize: boundSize,
+        fallbackRule: fallbackRule,
+        instanceManager: instanceManager,
+      );
+
+      verifyNever(mockApi.create(
+        argThat(isA<int>()),
+        argThat(isA<ResolutionInfo>()
+            .having((ResolutionInfo size) => size.width, 'width', 50)
+            .having((ResolutionInfo size) => size.height, 'height', 30)),
+        fallbackRule,
+      ));
+
+      ResolutionStrategy.detachedHighestAvailableStrategy(
+        instanceManager: instanceManager,
+      );
+
+      verifyNever(mockApi.create(
+        argThat(isA<int>()),
+        null,
+        null,
+      ));
+    });
+
+    test('HostApi create creates expected ResolutionStrategies', () {
+      final MockTestResolutionStrategyHostApi mockApi =
+          MockTestResolutionStrategyHostApi();
+      TestResolutionStrategyHostApi.setup(mockApi);
+      TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
+
+      final InstanceManager instanceManager = InstanceManager(
+        onWeakReferenceRemoved: (_) {},
+      );
+
+      const Size boundSize = Size(50, 30);
+      const int fallbackRule = 0;
+
+      final ResolutionStrategy instance = ResolutionStrategy(
+        boundSize: boundSize,
+        fallbackRule: fallbackRule,
+        instanceManager: instanceManager,
+      );
+
+      verify(mockApi.create(
+        instanceManager.getIdentifier(instance),
+        argThat(isA<ResolutionInfo>()
+            .having((ResolutionInfo size) => size.width, 'width', 50)
+            .having((ResolutionInfo size) => size.height, 'height', 30)),
+        fallbackRule,
+      ));
+
+      final ResolutionStrategy highestAvailableInstance =
+          ResolutionStrategy.highestAvailableStrategy(
+        instanceManager: instanceManager,
+      );
+
+      verify(mockApi.create(
+        instanceManager.getIdentifier(highestAvailableInstance),
+        null,
+        null,
+      ));
+    });
+  });
+}
diff --git a/packages/camera/camera_android_camerax/test/resolution_strategy_test.mocks.dart b/packages/camera/camera_android_camerax/test/resolution_strategy_test.mocks.dart
new file mode 100644
index 0000000..1a66738
--- /dev/null
+++ b/packages/camera/camera_android_camerax/test/resolution_strategy_test.mocks.dart
@@ -0,0 +1,69 @@
+// Mocks generated by Mockito 5.4.1 from annotations
+// in camera_android_camerax/test/resolution_strategy_test.dart.
+// Do not manually edit this file.
+
+// @dart=2.19
+
+// ignore_for_file: no_leading_underscores_for_library_prefixes
+import 'package:camera_android_camerax/src/camerax_library.g.dart' as _i3;
+import 'package:mockito/mockito.dart' as _i1;
+
+import 'test_camerax_library.g.dart' as _i2;
+
+// ignore_for_file: type=lint
+// ignore_for_file: avoid_redundant_argument_values
+// ignore_for_file: avoid_setters_without_getters
+// ignore_for_file: comment_references
+// ignore_for_file: implementation_imports
+// ignore_for_file: invalid_use_of_visible_for_testing_member
+// ignore_for_file: prefer_const_constructors
+// ignore_for_file: unnecessary_parenthesis
+// ignore_for_file: camel_case_types
+// ignore_for_file: subtype_of_sealed_class
+
+/// A class which mocks [TestResolutionStrategyHostApi].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockTestResolutionStrategyHostApi extends _i1.Mock
+    implements _i2.TestResolutionStrategyHostApi {
+  MockTestResolutionStrategyHostApi() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  void create(
+    int? identifier,
+    _i3.ResolutionInfo? boundSize,
+    int? fallbackRule,
+  ) =>
+      super.noSuchMethod(
+        Invocation.method(
+          #create,
+          [
+            identifier,
+            boundSize,
+            fallbackRule,
+          ],
+        ),
+        returnValueForMissingStub: null,
+      );
+}
+
+/// A class which mocks [TestInstanceManagerHostApi].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockTestInstanceManagerHostApi extends _i1.Mock
+    implements _i2.TestInstanceManagerHostApi {
+  MockTestInstanceManagerHostApi() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  void clear() => super.noSuchMethod(
+        Invocation.method(
+          #clear,
+          [],
+        ),
+        returnValueForMissingStub: null,
+      );
+}
diff --git a/packages/camera/camera_android_camerax/test/test_camerax_library.g.dart b/packages/camera/camera_android_camerax/test/test_camerax_library.g.dart
index 2c4afd1..6a80cf0 100644
--- a/packages/camera/camera_android_camerax/test/test_camerax_library.g.dart
+++ b/packages/camera/camera_android_camerax/test/test_camerax_library.g.dart
@@ -597,9 +597,6 @@
     if (value is ResolutionInfo) {
       buffer.putUint8(128);
       writeValue(buffer, value.encode());
-    } else if (value is ResolutionInfo) {
-      buffer.putUint8(129);
-      writeValue(buffer, value.encode());
     } else {
       super.writeValue(buffer, value);
     }
@@ -610,8 +607,6 @@
     switch (type) {
       case 128:
         return ResolutionInfo.decode(readValue(buffer)!);
-      case 129:
-        return ResolutionInfo.decode(readValue(buffer)!);
       default:
         return super.readValueOfType(type, buffer);
     }
@@ -623,7 +618,7 @@
       TestDefaultBinaryMessengerBinding.instance;
   static const MessageCodec<Object?> codec = _TestPreviewHostApiCodec();
 
-  void create(int identifier, int? rotation, ResolutionInfo? targetResolution);
+  void create(int identifier, int? rotation, int? resolutionSelectorId);
 
   int setSurfaceProvider(int identifier);
 
@@ -651,9 +646,8 @@
           assert(arg_identifier != null,
               'Argument for dev.flutter.pigeon.PreviewHostApi.create was null, expected non-null int.');
           final int? arg_rotation = (args[1] as int?);
-          final ResolutionInfo? arg_targetResolution =
-              (args[2] as ResolutionInfo?);
-          api.create(arg_identifier!, arg_rotation, arg_targetResolution);
+          final int? arg_resolutionSelectorId = (args[2] as int?);
+          api.create(arg_identifier!, arg_rotation, arg_resolutionSelectorId);
           return <Object?>[];
         });
       }
@@ -1033,35 +1027,12 @@
   }
 }
 
-class _TestImageCaptureHostApiCodec extends StandardMessageCodec {
-  const _TestImageCaptureHostApiCodec();
-  @override
-  void writeValue(WriteBuffer buffer, Object? value) {
-    if (value is ResolutionInfo) {
-      buffer.putUint8(128);
-      writeValue(buffer, value.encode());
-    } else {
-      super.writeValue(buffer, value);
-    }
-  }
-
-  @override
-  Object? readValueOfType(int type, ReadBuffer buffer) {
-    switch (type) {
-      case 128:
-        return ResolutionInfo.decode(readValue(buffer)!);
-      default:
-        return super.readValueOfType(type, buffer);
-    }
-  }
-}
-
 abstract class TestImageCaptureHostApi {
   static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding =>
       TestDefaultBinaryMessengerBinding.instance;
-  static const MessageCodec<Object?> codec = _TestImageCaptureHostApiCodec();
+  static const MessageCodec<Object?> codec = StandardMessageCodec();
 
-  void create(int identifier, int? flashMode, ResolutionInfo? targetResolution);
+  void create(int identifier, int? flashMode, int? resolutionSelectorId);
 
   void setFlashMode(int identifier, int flashMode);
 
@@ -1087,9 +1058,8 @@
           assert(arg_identifier != null,
               'Argument for dev.flutter.pigeon.ImageCaptureHostApi.create was null, expected non-null int.');
           final int? arg_flashMode = (args[1] as int?);
-          final ResolutionInfo? arg_targetResolution =
-              (args[2] as ResolutionInfo?);
-          api.create(arg_identifier!, arg_flashMode, arg_targetResolution);
+          final int? arg_resolutionSelectorId = (args[2] as int?);
+          api.create(arg_identifier!, arg_flashMode, arg_resolutionSelectorId);
           return <Object?>[];
         });
       }
@@ -1144,8 +1114,8 @@
   }
 }
 
-class _TestImageAnalysisHostApiCodec extends StandardMessageCodec {
-  const _TestImageAnalysisHostApiCodec();
+class _TestResolutionStrategyHostApiCodec extends StandardMessageCodec {
+  const _TestResolutionStrategyHostApiCodec();
   @override
   void writeValue(WriteBuffer buffer, Object? value) {
     if (value is ResolutionInfo) {
@@ -1167,12 +1137,128 @@
   }
 }
 
+abstract class TestResolutionStrategyHostApi {
+  static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding =>
+      TestDefaultBinaryMessengerBinding.instance;
+  static const MessageCodec<Object?> codec =
+      _TestResolutionStrategyHostApiCodec();
+
+  void create(int identifier, ResolutionInfo? boundSize, int? fallbackRule);
+
+  static void setup(TestResolutionStrategyHostApi? api,
+      {BinaryMessenger? binaryMessenger}) {
+    {
+      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+          'dev.flutter.pigeon.ResolutionStrategyHostApi.create', codec,
+          binaryMessenger: binaryMessenger);
+      if (api == null) {
+        _testBinaryMessengerBinding!.defaultBinaryMessenger
+            .setMockDecodedMessageHandler<Object?>(channel, null);
+      } else {
+        _testBinaryMessengerBinding!.defaultBinaryMessenger
+            .setMockDecodedMessageHandler<Object?>(channel,
+                (Object? message) async {
+          assert(message != null,
+              'Argument for dev.flutter.pigeon.ResolutionStrategyHostApi.create was null.');
+          final List<Object?> args = (message as List<Object?>?)!;
+          final int? arg_identifier = (args[0] as int?);
+          assert(arg_identifier != null,
+              'Argument for dev.flutter.pigeon.ResolutionStrategyHostApi.create was null, expected non-null int.');
+          final ResolutionInfo? arg_boundSize = (args[1] as ResolutionInfo?);
+          final int? arg_fallbackRule = (args[2] as int?);
+          api.create(arg_identifier!, arg_boundSize, arg_fallbackRule);
+          return <Object?>[];
+        });
+      }
+    }
+  }
+}
+
+abstract class TestResolutionSelectorHostApi {
+  static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding =>
+      TestDefaultBinaryMessengerBinding.instance;
+  static const MessageCodec<Object?> codec = StandardMessageCodec();
+
+  void create(int identifier, int? resolutionStrategyIdentifier,
+      int? aspectRatioStrategyIdentifier);
+
+  static void setup(TestResolutionSelectorHostApi? api,
+      {BinaryMessenger? binaryMessenger}) {
+    {
+      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+          'dev.flutter.pigeon.ResolutionSelectorHostApi.create', codec,
+          binaryMessenger: binaryMessenger);
+      if (api == null) {
+        _testBinaryMessengerBinding!.defaultBinaryMessenger
+            .setMockDecodedMessageHandler<Object?>(channel, null);
+      } else {
+        _testBinaryMessengerBinding!.defaultBinaryMessenger
+            .setMockDecodedMessageHandler<Object?>(channel,
+                (Object? message) async {
+          assert(message != null,
+              'Argument for dev.flutter.pigeon.ResolutionSelectorHostApi.create was null.');
+          final List<Object?> args = (message as List<Object?>?)!;
+          final int? arg_identifier = (args[0] as int?);
+          assert(arg_identifier != null,
+              'Argument for dev.flutter.pigeon.ResolutionSelectorHostApi.create was null, expected non-null int.');
+          final int? arg_resolutionStrategyIdentifier = (args[1] as int?);
+          final int? arg_aspectRatioStrategyIdentifier = (args[2] as int?);
+          api.create(arg_identifier!, arg_resolutionStrategyIdentifier,
+              arg_aspectRatioStrategyIdentifier);
+          return <Object?>[];
+        });
+      }
+    }
+  }
+}
+
+abstract class TestAspectRatioStrategyHostApi {
+  static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding =>
+      TestDefaultBinaryMessengerBinding.instance;
+  static const MessageCodec<Object?> codec = StandardMessageCodec();
+
+  void create(int identifier, int preferredAspectRatio, int fallbackRule);
+
+  static void setup(TestAspectRatioStrategyHostApi? api,
+      {BinaryMessenger? binaryMessenger}) {
+    {
+      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+          'dev.flutter.pigeon.AspectRatioStrategyHostApi.create', codec,
+          binaryMessenger: binaryMessenger);
+      if (api == null) {
+        _testBinaryMessengerBinding!.defaultBinaryMessenger
+            .setMockDecodedMessageHandler<Object?>(channel, null);
+      } else {
+        _testBinaryMessengerBinding!.defaultBinaryMessenger
+            .setMockDecodedMessageHandler<Object?>(channel,
+                (Object? message) async {
+          assert(message != null,
+              'Argument for dev.flutter.pigeon.AspectRatioStrategyHostApi.create was null.');
+          final List<Object?> args = (message as List<Object?>?)!;
+          final int? arg_identifier = (args[0] as int?);
+          assert(arg_identifier != null,
+              'Argument for dev.flutter.pigeon.AspectRatioStrategyHostApi.create was null, expected non-null int.');
+          final int? arg_preferredAspectRatio = (args[1] as int?);
+          assert(arg_preferredAspectRatio != null,
+              'Argument for dev.flutter.pigeon.AspectRatioStrategyHostApi.create was null, expected non-null int.');
+          final int? arg_fallbackRule = (args[2] as int?);
+          assert(arg_fallbackRule != null,
+              'Argument for dev.flutter.pigeon.AspectRatioStrategyHostApi.create was null, expected non-null int.');
+          api.create(
+              arg_identifier!, arg_preferredAspectRatio!, arg_fallbackRule!);
+          return <Object?>[];
+        });
+      }
+    }
+  }
+}
+
 abstract class TestImageAnalysisHostApi {
   static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding =>
       TestDefaultBinaryMessengerBinding.instance;
-  static const MessageCodec<Object?> codec = _TestImageAnalysisHostApiCodec();
+  static const MessageCodec<Object?> codec = StandardMessageCodec();
 
-  void create(int identifier, ResolutionInfo? targetResolutionIdentifier);
+  void create(int identifier, int? resolutionSelectorId);
 
   void setAnalyzer(int identifier, int analyzerIdentifier);
 
@@ -1197,9 +1283,8 @@
           final int? arg_identifier = (args[0] as int?);
           assert(arg_identifier != null,
               'Argument for dev.flutter.pigeon.ImageAnalysisHostApi.create was null, expected non-null int.');
-          final ResolutionInfo? arg_targetResolutionIdentifier =
-              (args[1] as ResolutionInfo?);
-          api.create(arg_identifier!, arg_targetResolutionIdentifier);
+          final int? arg_resolutionSelectorId = (args[1] as int?);
+          api.create(arg_identifier!, arg_resolutionSelectorId);
           return <Object?>[];
         });
       }