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