88import androidx .annotation .NonNull ;
99import androidx .annotation .VisibleForTesting ;
1010import androidx .camera .core .CameraControl ;
11+ import androidx .camera .core .FocusMeteringAction ;
12+ import androidx .camera .core .FocusMeteringResult ;
1113import androidx .core .content .ContextCompat ;
1214import com .google .common .util .concurrent .FutureCallback ;
1315import com .google .common .util .concurrent .Futures ;
1416import com .google .common .util .concurrent .ListenableFuture ;
17+ import io .flutter .plugin .common .BinaryMessenger ;
1518import io .flutter .plugins .camerax .GeneratedCameraXLibrary .CameraControlHostApi ;
19+ import io .flutter .plugins .camerax .GeneratedCameraXLibrary .Result ;
1620import java .util .Objects ;
1721
1822/**
@@ -29,6 +33,8 @@ public class CameraControlHostApiImpl implements CameraControlHostApi {
2933 @ VisibleForTesting
3034 public static class CameraControlProxy {
3135 Context context ;
36+ BinaryMessenger binaryMessenger ;
37+ InstanceManager instanceManager ;
3238
3339 /** Enables or disables the torch of the specified {@link CameraControl} instance. */
3440 @ NonNull
@@ -82,6 +88,85 @@ public void onFailure(Throwable t) {
8288 },
8389 ContextCompat .getMainExecutor (context ));
8490 }
91+
92+ /**
93+ * Starts a focus and metering action configured by the {@code FocusMeteringAction}.
94+ *
95+ * <p>Will trigger an auto focus action and enable auto focus/auto exposure/auto white balance
96+ * metering regions.
97+ */
98+ public void startFocusAndMetering (
99+ @ NonNull CameraControl cameraControl ,
100+ @ NonNull FocusMeteringAction focusMeteringAction ,
101+ @ NonNull GeneratedCameraXLibrary .Result <Long > result ) {
102+ ListenableFuture <FocusMeteringResult > focusMeteringResultFuture =
103+ cameraControl .startFocusAndMetering (focusMeteringAction );
104+
105+ Futures .addCallback (
106+ focusMeteringResultFuture ,
107+ new FutureCallback <FocusMeteringResult >() {
108+ public void onSuccess (FocusMeteringResult focusMeteringResult ) {
109+ final FocusMeteringResultFlutterApiImpl flutterApi =
110+ new FocusMeteringResultFlutterApiImpl (binaryMessenger , instanceManager );
111+ flutterApi .create (focusMeteringResult , reply -> {});
112+ result .success (instanceManager .getIdentifierForStrongReference (focusMeteringResult ));
113+ }
114+
115+ public void onFailure (Throwable t ) {
116+ result .error (t );
117+ }
118+ },
119+ ContextCompat .getMainExecutor (context ));
120+ }
121+
122+ /**
123+ * Cancels current {@code FocusMeteringAction} and clears auto focus/auto exposure/auto white
124+ * balance regions.
125+ */
126+ public void cancelFocusAndMetering (
127+ @ NonNull CameraControl cameraControl , @ NonNull Result <Void > result ) {
128+ ListenableFuture <Void > cancelFocusAndMeteringFuture = cameraControl .cancelFocusAndMetering ();
129+
130+ Futures .addCallback (
131+ cancelFocusAndMeteringFuture ,
132+ new FutureCallback <Void >() {
133+ public void onSuccess (Void voidResult ) {
134+ result .success (null );
135+ }
136+
137+ public void onFailure (Throwable t ) {
138+ result .error (t );
139+ }
140+ },
141+ ContextCompat .getMainExecutor (context ));
142+ }
143+
144+ /**
145+ * Sets the exposure compensation index for the specified {@link CameraControl} instance and
146+ * returns the new target exposure value.
147+ *
148+ * <p>The exposure compensation value set on the camera must be within the range of {@code
149+ * ExposureState#getExposureCompensationRange()} for the current {@code ExposureState} for the
150+ * call to succeed.
151+ */
152+ public void setExposureCompensationIndex (
153+ @ NonNull CameraControl cameraControl , @ NonNull Long index , @ NonNull Result <Long > result ) {
154+ ListenableFuture <Integer > setExposureCompensationIndexFuture =
155+ cameraControl .setExposureCompensationIndex (index .intValue ());
156+
157+ Futures .addCallback (
158+ setExposureCompensationIndexFuture ,
159+ new FutureCallback <Integer >() {
160+ public void onSuccess (Integer integerResult ) {
161+ result .success (integerResult .longValue ());
162+ }
163+
164+ public void onFailure (Throwable t ) {
165+ result .error (t );
166+ }
167+ },
168+ ContextCompat .getMainExecutor (context ));
169+ }
85170 }
86171
87172 /**
@@ -90,8 +175,10 @@ public void onFailure(Throwable t) {
90175 * @param instanceManager maintains instances stored to communicate with attached Dart objects
91176 */
92177 public CameraControlHostApiImpl (
93- @ NonNull InstanceManager instanceManager , @ NonNull Context context ) {
94- this (instanceManager , new CameraControlProxy (), context );
178+ @ NonNull BinaryMessenger binaryMessenger ,
179+ @ NonNull InstanceManager instanceManager ,
180+ @ NonNull Context context ) {
181+ this (binaryMessenger , instanceManager , new CameraControlProxy (), context );
95182 }
96183
97184 /**
@@ -103,12 +190,16 @@ public CameraControlHostApiImpl(
103190 */
104191 @ VisibleForTesting
105192 CameraControlHostApiImpl (
193+ @ NonNull BinaryMessenger binaryMessenger ,
106194 @ NonNull InstanceManager instanceManager ,
107195 @ NonNull CameraControlProxy proxy ,
108196 @ NonNull Context context ) {
109197 this .instanceManager = instanceManager ;
110198 this .proxy = proxy ;
111199 proxy .context = context ;
200+ // proxy.startFocusAndMetering needs to access these to create a FocusMeteringResult when it becomes available:
201+ proxy .instanceManager = instanceManager ;
202+ proxy .binaryMessenger = binaryMessenger ;
112203 }
113204
114205 /**
@@ -127,16 +218,38 @@ public void enableTorch(
127218 @ NonNull Long identifier ,
128219 @ NonNull Boolean torch ,
129220 @ NonNull GeneratedCameraXLibrary .Result <Void > result ) {
130- proxy .enableTorch (
131- Objects .requireNonNull (instanceManager .getInstance (identifier )), torch , result );
221+ proxy .enableTorch (getCameraControlInstance (identifier ), torch , result );
132222 }
133223
134224 @ Override
135225 public void setZoomRatio (
136226 @ NonNull Long identifier ,
137227 @ NonNull Double ratio ,
138228 @ NonNull GeneratedCameraXLibrary .Result <Void > result ) {
139- proxy .setZoomRatio (
140- Objects .requireNonNull (instanceManager .getInstance (identifier )), ratio , result );
229+ proxy .setZoomRatio (getCameraControlInstance (identifier ), ratio , result );
230+ }
231+
232+ @ Override
233+ public void startFocusAndMetering (
234+ @ NonNull Long identifier , @ NonNull Long focusMeteringActionId , @ NonNull Result <Long > result ) {
235+ proxy .startFocusAndMetering (
236+ getCameraControlInstance (identifier ),
237+ Objects .requireNonNull (instanceManager .getInstance (focusMeteringActionId )),
238+ result );
239+ }
240+
241+ @ Override
242+ public void cancelFocusAndMetering (@ NonNull Long identifier , @ NonNull Result <Void > result ) {
243+ proxy .cancelFocusAndMetering (getCameraControlInstance (identifier ), result );
244+ }
245+
246+ @ Override
247+ public void setExposureCompensationIndex (
248+ @ NonNull Long identifier , @ NonNull Long index , @ NonNull Result <Long > result ) {
249+ proxy .setExposureCompensationIndex (getCameraControlInstance (identifier ), index , result );
250+ }
251+
252+ private CameraControl getCameraControlInstance (@ NonNull Long identifier ) {
253+ return Objects .requireNonNull (instanceManager .getInstance (identifier ));
141254 }
142255}
0 commit comments