1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.camera.core;
18 
19 import androidx.annotation.IntDef;
20 import androidx.annotation.IntRange;
21 import androidx.annotation.RestrictTo;
22 import androidx.core.util.Preconditions;
23 
24 import com.google.common.util.concurrent.ListenableFuture;
25 
26 import org.jspecify.annotations.NonNull;
27 
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.concurrent.TimeUnit;
34 
35 /**
36  * A configuration used to trigger a focus and/or metering action.
37  *
38  * <p>A {@link FocusMeteringAction} must be created by the {@link Builder}. To construct a
39  * {@link Builder}, a {@link MeteringPoint} is required to specify the focus/metering area. Apps
40  * can use various {@link MeteringPointFactory} to create the points. After the
41  * {@link FocusMeteringAction} is built, apps can pass it to
42  * {@link CameraControl#startFocusAndMetering(FocusMeteringAction)} to initiate the focus
43  * and metering action.
44  *
45  * <p>When specifying a {@link MeteringPoint}, a metering mode can also be specified. Metering
46  * mode is a combination of flags consisting of {@link #FLAG_AF}, {@link #FLAG_AE}, and
47  * {@link #FLAG_AWB}. This combination indicates whether the {@link MeteringPoint} is
48  * used to set an AF(Auto Focus) region, AE(Auto Exposure) region or AWB(Auto White Balance) region.
49  * The default meteringMode is {@link #FLAG_AF} | {@link #FLAG_AE} | {@link #FLAG_AWB} which
50  * means the point is used for all AF/AE/AWB regions. Apps can set the proper metering mode to
51  * optionally exclude some 3A regions. Multiple regions for specific 3A types are also supported
52  * via {@link Builder#addPoint(MeteringPoint)} or {@link Builder#addPoint(MeteringPoint, int)}.
53  * An app can also use this API to enable different regions for AF and AE respectively.
54  *
55  * <p>If any AF points are specified, it will trigger autofocus to start a manual scan. When
56  * focus is locked and the specified AF/AE/AWB regions are updated in capture result, the returned
57  * {@link ListenableFuture} in {@link CameraControl#startFocusAndMetering(FocusMeteringAction)}
58  * will complete with {@link FocusMeteringResult#isFocusSuccessful()} set to indicate if focus is
59  * done successfully or not. If an AF point is not specified, it will not trigger autofocus and
60  * simply wait for specified AE/AWB regions being updated to complete the returned
61  * {@link ListenableFuture}. In the case of AF points not specified,
62  * {@link FocusMeteringResult#isFocusSuccessful()} will be set to false. If Af points are
63  * specified but current camera does not support auto focus,
64  * {@link FocusMeteringResult#isFocusSuccessful()} will be set to true .
65  *
66  * <p>App can set a auto-cancel duration to let CameraX call
67  * {@link CameraControl#cancelFocusAndMetering()} automatically in the specified duration. By
68  * default the auto-cancel duration is 5 seconds. Apps can call {@link Builder#disableAutoCancel()}
69  * to disable auto-cancel.
70  */
71 public final class FocusMeteringAction {
72 
73     /**
74      * A flag used in metering mode indicating the AF (Auto Focus) region is enabled. An autofocus
75      * scan is also triggered when FLAG_AF is assigned.
76      */
77     public static final int FLAG_AF = 1;
78 
79     /**
80      * A flag used in metering mode indicating the AE (Auto Exposure) region is enabled.
81      */
82     public static final int FLAG_AE = 1 << 1;
83 
84     /**
85      * A flag used in metering mode indicating the AWB (Auto White Balance) region is enabled.
86      */
87     public static final int FLAG_AWB = 1 << 2;
88 
89     @MeteringMode
90     static final int DEFAULT_METERING_MODE = FLAG_AF | FLAG_AE | FLAG_AWB;
91 
92     /** The default duration for auto-cancelling a focus-metering action. */
93     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
94     public static final long DEFAULT_AUTO_CANCEL_DURATION_MILLIS = 5000;
95 
96     private final List<MeteringPoint> mMeteringPointsAf;
97     private final List<MeteringPoint> mMeteringPointsAe;
98     private final List<MeteringPoint> mMeteringPointsAwb;
99     private final long mAutoCancelDurationInMillis;
100 
101     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
FocusMeteringAction(Builder builder)102     FocusMeteringAction(Builder builder) {
103         mMeteringPointsAf = Collections.unmodifiableList(builder.mMeteringPointsAf);
104         mMeteringPointsAe = Collections.unmodifiableList(builder.mMeteringPointsAe);
105         mMeteringPointsAwb = Collections.unmodifiableList(builder.mMeteringPointsAwb);
106         mAutoCancelDurationInMillis = builder.mAutoCancelDurationInMillis;
107     }
108 
109     /**
110      * Returns auto-cancel duration.  Returns 0 if auto-cancel is disabled.
111      */
getAutoCancelDurationInMillis()112     public long getAutoCancelDurationInMillis() {
113         return mAutoCancelDurationInMillis;
114     }
115 
116     /**
117      * Returns all {@link MeteringPoint}s used for AF regions.
118      */
getMeteringPointsAf()119     public @NonNull List<MeteringPoint> getMeteringPointsAf() {
120         return mMeteringPointsAf;
121     }
122 
123     /**
124      * Returns all {@link MeteringPoint}s used for AE regions.
125      */
getMeteringPointsAe()126     public @NonNull List<MeteringPoint> getMeteringPointsAe() {
127         return mMeteringPointsAe;
128     }
129 
130     /**
131      * Returns all {@link MeteringPoint}s used for AWB regions.
132      */
getMeteringPointsAwb()133     public @NonNull List<MeteringPoint> getMeteringPointsAwb() {
134         return mMeteringPointsAwb;
135     }
136 
137     /**
138      * Returns if auto-cancel is enabled or not.
139      */
isAutoCancelEnabled()140     public boolean isAutoCancelEnabled() {
141         return mAutoCancelDurationInMillis > 0;
142     }
143 
144     /**
145      * Focus/Metering mode used to specify which 3A regions is activated for corresponding
146      * {@link MeteringPoint}.
147      *
148      */
149     @IntDef(flag = true, value = {FLAG_AF, FLAG_AE, FLAG_AWB})
150     @Retention(RetentionPolicy.SOURCE)
151     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
152     public @interface MeteringMode {
153     }
154 
155     /**
156      * The builder used to create the {@link FocusMeteringAction}.
157      */
158     public static class Builder {
159         @SuppressWarnings("WeakerAccess") /* synthetic accessor */
160         final List<MeteringPoint> mMeteringPointsAf = new ArrayList<>();
161         @SuppressWarnings("WeakerAccess") /* synthetic accessor */
162         final List<MeteringPoint> mMeteringPointsAe = new ArrayList<>();
163         @SuppressWarnings("WeakerAccess") /* synthetic accessor */
164         final List<MeteringPoint> mMeteringPointsAwb = new ArrayList<>();
165         @SuppressWarnings("WeakerAccess") /* synthetic accessor */
166                 long mAutoCancelDurationInMillis = DEFAULT_AUTO_CANCEL_DURATION_MILLIS;
167 
168         /**
169          * Creates a Builder from a {@link MeteringPoint} with default mode {@link #FLAG_AF} |
170          * {@link #FLAG_AE} | {@link #FLAG_AWB}.
171          */
Builder(@onNull MeteringPoint point)172         public Builder(@NonNull MeteringPoint point) {
173             this(point, DEFAULT_METERING_MODE);
174         }
175 
176         /**
177          * Creates a Builder from a {@link MeteringPoint} and MeteringMode.
178          *
179          * <p>Metering mode is a combination of flags consisting of {@link #FLAG_AF},
180          * {@link #FLAG_AE}, and {@link #FLAG_AWB}. This combination indicates whether the
181          * {@link MeteringPoint} is used to set AF(Auto Focus) region, AE(Auto
182          * Exposure) region or AWB(Auto White Balance) region.
183          */
Builder(@onNull MeteringPoint point, @MeteringMode int meteringMode)184         public Builder(@NonNull MeteringPoint point, @MeteringMode int meteringMode) {
185             addPoint(point, meteringMode);
186         }
187 
188         /**
189          * Create a Builder from a {@link FocusMeteringAction}.
190          */
191         @RestrictTo(RestrictTo.Scope.LIBRARY)
Builder(@onNull FocusMeteringAction focusMeteringAction)192         public Builder(@NonNull FocusMeteringAction focusMeteringAction) {
193             mMeteringPointsAf.addAll(focusMeteringAction.getMeteringPointsAf());
194             mMeteringPointsAe.addAll(focusMeteringAction.getMeteringPointsAe());
195             mMeteringPointsAwb.addAll(focusMeteringAction.getMeteringPointsAwb());
196             mAutoCancelDurationInMillis = focusMeteringAction.getAutoCancelDurationInMillis();
197         }
198 
199         /**
200          * Adds another {@link MeteringPoint} with default metering mode {@link #FLAG_AF} |
201          * {@link #FLAG_AE} | {@link #FLAG_AWB}.
202          *
203          * <p>The points added here will be appended in order after the point set in builder
204          * constructor.
205          *
206          * <p>If more points are added than what current device supports for AF/AE/AWB, only the
207          * first point and then in order up to the number of points supported on the device
208          * will be enabled.
209          *
210          * <p>If none of the points is supported on the device, this
211          * {@link FocusMeteringAction} will cause
212          * {@link CameraControl#startFocusAndMetering(FocusMeteringAction)} to fail.
213          *
214          * @see CameraControl#startFocusAndMetering(FocusMeteringAction)
215          */
addPoint(@onNull MeteringPoint point)216         public @NonNull Builder addPoint(@NonNull MeteringPoint point) {
217             return addPoint(point, DEFAULT_METERING_MODE);
218         }
219 
220         /**
221          * Adds another {@link MeteringPoint} with specified meteringMode.
222          *
223          * <p>Metering mode is a combination of flags consisting of {@link #FLAG_AF},
224          * {@link #FLAG_AE}, and {@link #FLAG_AWB}. This combination indicates whether the
225          * {@link MeteringPoint} is used to set AF(Auto Focus) region, AE(Auto Exposure) region
226          * or AWB(Auto White Balance) region.
227          *
228          * <p>The points added here will be appended in order after the point set in builder
229          * constructor.
230          *
231          * <p>If more points are added than what current device supports for AF/AE/AWB, only the
232          * first point and then in order up to the number of points supported on the device
233          * will be enabled.
234          *
235          * <p>If none of the points is supported on the device, this
236          * {@link FocusMeteringAction} will cause
237          * {@link CameraControl#startFocusAndMetering(FocusMeteringAction)} to fail.
238          *
239          * @see CameraControl#startFocusAndMetering(FocusMeteringAction)
240          */
addPoint(@onNull MeteringPoint point, @MeteringMode int meteringMode)241         public @NonNull Builder addPoint(@NonNull MeteringPoint point,
242                 @MeteringMode int meteringMode) {
243             Preconditions.checkArgument(point != null, "Point cannot be null.");
244             Preconditions.checkArgument(
245                     (meteringMode >= FLAG_AF) && (meteringMode <= (FLAG_AF | FLAG_AE | FLAG_AWB)),
246                     "Invalid metering mode " + meteringMode);
247 
248             if ((meteringMode & FLAG_AF) != 0) {
249                 mMeteringPointsAf.add(point);
250             }
251             if ((meteringMode & FLAG_AE) != 0) {
252                 mMeteringPointsAe.add(point);
253             }
254             if ((meteringMode & FLAG_AWB) != 0) {
255                 mMeteringPointsAwb.add(point);
256             }
257             return this;
258         }
259 
260         /**
261          * Sets the auto-cancel duration. After set, {@link CameraControl#cancelFocusAndMetering()}
262          * will be called in specified duration. By default, auto-cancel is enabled with 5
263          * seconds duration. The duration must be greater than or equal to 1 otherwise it
264          * will throw a {@link IllegalArgumentException}.
265          */
setAutoCancelDuration(@ntRangefrom = 1) long duration, @NonNull TimeUnit timeUnit)266         public @NonNull Builder setAutoCancelDuration(@IntRange(from = 1) long duration,
267                 @NonNull TimeUnit timeUnit) {
268             Preconditions.checkArgument(duration >= 1, "autoCancelDuration must be at least 1");
269             mAutoCancelDurationInMillis = timeUnit.toMillis(duration);
270             return this;
271         }
272 
273         /**
274          * Disables the auto-cancel.
275          */
disableAutoCancel()276         public @NonNull Builder disableAutoCancel() {
277             mAutoCancelDurationInMillis = 0;
278             return this;
279         }
280 
281         /**
282          *
283          * Remove all points of the given meteringMode.
284          */
285         @RestrictTo(RestrictTo.Scope.LIBRARY)
removePoints(@eteringMode int meteringMode)286         public @NonNull Builder removePoints(@MeteringMode int meteringMode) {
287             if ((meteringMode & FLAG_AF) != 0) {
288                 mMeteringPointsAf.clear();
289             }
290 
291             if ((meteringMode & FLAG_AE) != 0) {
292                 mMeteringPointsAe.clear();
293             }
294 
295             if ((meteringMode & FLAG_AWB) != 0) {
296                 mMeteringPointsAwb.clear();
297             }
298             return this;
299         }
300 
301         /**
302          * Builds the {@link FocusMeteringAction} instance.
303          */
build()304         public @NonNull FocusMeteringAction build() {
305             return new FocusMeteringAction(this);
306         }
307 
308     }
309 }
310