1 /*
2  * Copyright (C) 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 android.app.Application;
20 import android.os.Handler;
21 import android.util.Log;
22 
23 import androidx.annotation.IntDef;
24 import androidx.annotation.IntRange;
25 import androidx.annotation.OptIn;
26 import androidx.annotation.RestrictTo;
27 import androidx.annotation.RestrictTo.Scope;
28 import androidx.camera.core.impl.CameraDeviceSurfaceManager;
29 import androidx.camera.core.impl.CameraFactory;
30 import androidx.camera.core.impl.Config;
31 import androidx.camera.core.impl.MutableConfig;
32 import androidx.camera.core.impl.MutableOptionsBundle;
33 import androidx.camera.core.impl.OptionsBundle;
34 import androidx.camera.core.impl.QuirkSettings;
35 import androidx.camera.core.impl.UseCaseConfigFactory;
36 import androidx.camera.core.internal.TargetConfig;
37 
38 import org.jspecify.annotations.NonNull;
39 import org.jspecify.annotations.Nullable;
40 
41 import java.lang.annotation.Retention;
42 import java.lang.annotation.RetentionPolicy;
43 import java.util.Objects;
44 import java.util.UUID;
45 import java.util.concurrent.Executor;
46 
47 /**
48  * A configuration for adding implementation and user-specific behavior to CameraX.
49  *
50  * <p>CameraXConfig provides customizable options for camera provider instances that persist for
51  * the lifetime of the provider.
52  *
53  * <p>An implementation of CameraXConfig can be provided by subclassing the
54  * {@link Application} object and implementing {@link CameraXConfig.Provider}. Alternatively,
55  * other methods configuration exist such as
56  * {@link androidx.camera.lifecycle.ProcessCameraProvider#configureInstance(CameraXConfig)}.
57  * {@linkplain androidx.camera.lifecycle.ProcessCameraProvider#getInstance(android.content.Context)
58  * Examples} of how this is used can be found in the {@link androidx.camera.lifecycle} package.
59  *
60  * <p>Applications can create and use {@linkplain androidx.camera.camera2.Camera2Config the
61  * implementation} of CameraXConfig provided in {@link androidx.camera.camera2}.
62  *
63  * @see androidx.camera.lifecycle.ProcessCameraProvider#configureInstance(CameraXConfig)
64  * @see CameraXConfig.Builder
65  */
66 @SuppressWarnings("HiddenSuperclass")
67 public final class CameraXConfig implements TargetConfig<CameraX> {
68 
69     /**
70      * Unknown CameraX config impl type.
71      */
72     @RestrictTo(Scope.LIBRARY_GROUP)
73     public static final int CAMERAX_CONFIG_IMPL_TYPE_UNKNOWN = -1;
74     /**
75      * camera-camera2 CameraX config impl type.
76      */
77     @RestrictTo(Scope.LIBRARY_GROUP)
78     public static final int CAMERAX_CONFIG_IMPL_TYPE_CAMERA_CAMERA2 = 0;
79     /**
80      * camera-camera2-pipe-integration CameraX config impl type.
81      */
82     @RestrictTo(Scope.LIBRARY_GROUP)
83     public static final int CAMERAX_CONFIG_IMPL_TYPE_PIPE = 1;
84 
85     /**
86      * The different implementation types the CameraXConfig can be configured for.
87      */
88     @IntDef({CAMERAX_CONFIG_IMPL_TYPE_UNKNOWN, CAMERAX_CONFIG_IMPL_TYPE_CAMERA_CAMERA2,
89             CAMERAX_CONFIG_IMPL_TYPE_PIPE})
90     @Retention(RetentionPolicy.SOURCE)
91     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
92     public @interface ImplType {
93     }
94 
95     /**
96      * An interface which can be implemented to provide the configuration for CameraX.
97      *
98      * <p>When implemented by an {@link Application}, this can provide on-demand initialization
99      * of CameraX.
100      *
101      * <p>{@linkplain
102      * androidx.camera.lifecycle.ProcessCameraProvider#getInstance(android.content.Context)
103      * Examples} of how this is used can be found in the {@link androidx.camera.lifecycle} package.
104      */
105     public interface Provider {
106         /** Returns the configuration to use for initializing an instance of CameraX. */
getCameraXConfig()107         @NonNull CameraXConfig getCameraXConfig();
108     }
109 
110     // Option Declarations:
111     // *********************************************************************************************
112 
113     static final Option<CameraFactory.Provider> OPTION_CAMERA_FACTORY_PROVIDER =
114             Option.create("camerax.core.appConfig.cameraFactoryProvider",
115                     CameraFactory.Provider.class);
116     static final Option<CameraDeviceSurfaceManager.Provider>
117             OPTION_DEVICE_SURFACE_MANAGER_PROVIDER =
118             Option.create(
119                     "camerax.core.appConfig.deviceSurfaceManagerProvider",
120                     CameraDeviceSurfaceManager.Provider.class);
121     static final Option<UseCaseConfigFactory.Provider> OPTION_USECASE_CONFIG_FACTORY_PROVIDER =
122             Option.create(
123                     "camerax.core.appConfig.useCaseConfigFactoryProvider",
124                     UseCaseConfigFactory.Provider.class);
125     static final Option<Executor> OPTION_CAMERA_EXECUTOR =
126             Option.create(
127                     "camerax.core.appConfig.cameraExecutor",
128                     Executor.class);
129     static final Option<Handler> OPTION_SCHEDULER_HANDLER =
130             Option.create(
131                     "camerax.core.appConfig.schedulerHandler",
132                     Handler.class);
133     static final Option<Integer> OPTION_MIN_LOGGING_LEVEL =
134             Option.create(
135                     "camerax.core.appConfig.minimumLoggingLevel",
136                     int.class);
137     static final Option<CameraSelector> OPTION_AVAILABLE_CAMERAS_LIMITER =
138             Option.create(
139                     "camerax.core.appConfig.availableCamerasLimiter",
140                     CameraSelector.class);
141 
142     static final Option<Long> OPTION_CAMERA_OPEN_RETRY_MAX_TIMEOUT_IN_MILLIS_WHILE_RESUMING =
143             Option.create(
144                     "camerax.core.appConfig.cameraOpenRetryMaxTimeoutInMillisWhileResuming",
145                     long.class);
146 
147     @OptIn(markerClass = ExperimentalRetryPolicy.class)
148     static final Option<RetryPolicy> OPTION_CAMERA_PROVIDER_INIT_RETRY_POLICY =
149             Option.create(
150                     "camerax.core.appConfig.cameraProviderInitRetryPolicy",
151                     RetryPolicy.class);
152 
153     static final long DEFAULT_OPTION_CAMERA_OPEN_RETRY_MAX_TIMEOUT_IN_MILLIS_WHILE_RESUMING = -1L;
154 
155     static final Option<QuirkSettings> OPTION_QUIRK_SETTINGS =
156             Option.create(
157                     "camerax.core.appConfig.quirksSettings",
158                     QuirkSettings.class);
159 
160     static final Option<Integer> OPTION_CONFIG_IMPL_TYPE =
161             Option.create("camerax.core.appConfig.configImplType", int.class);
162 
163     // *********************************************************************************************
164 
165     private final OptionsBundle mConfig;
166 
CameraXConfig(OptionsBundle options)167     CameraXConfig(OptionsBundle options) {
168         mConfig = options;
169     }
170 
171     /**
172      * Returns the {@link CameraFactory} implementation for the application.
173      *
174      */
175     @RestrictTo(Scope.LIBRARY_GROUP)
getCameraFactoryProvider( CameraFactory.@ullable Provider valueIfMissing)176     public CameraFactory.@Nullable Provider getCameraFactoryProvider(
177             CameraFactory.@Nullable Provider valueIfMissing) {
178         return mConfig.retrieveOption(OPTION_CAMERA_FACTORY_PROVIDER, valueIfMissing);
179     }
180 
181     /**
182      * Returns the {@link CameraDeviceSurfaceManager} implementation for the application.
183      *
184      */
185     @RestrictTo(Scope.LIBRARY_GROUP)
getDeviceSurfaceManagerProvider( CameraDeviceSurfaceManager.@ullable Provider valueIfMissing)186     public CameraDeviceSurfaceManager.@Nullable Provider getDeviceSurfaceManagerProvider(
187             CameraDeviceSurfaceManager.@Nullable Provider valueIfMissing) {
188         return mConfig.retrieveOption(OPTION_DEVICE_SURFACE_MANAGER_PROVIDER, valueIfMissing);
189     }
190 
191     /**
192      * Returns the {@link UseCaseConfigFactory} implementation for the application.
193      *
194      * <p>This factory should produce all default configurations for the application's use cases.
195      *
196      */
197     @RestrictTo(Scope.LIBRARY_GROUP)
getUseCaseConfigFactoryProvider( UseCaseConfigFactory.@ullable Provider valueIfMissing)198     public UseCaseConfigFactory.@Nullable Provider getUseCaseConfigFactoryProvider(
199             UseCaseConfigFactory.@Nullable Provider valueIfMissing) {
200         return mConfig.retrieveOption(OPTION_USECASE_CONFIG_FACTORY_PROVIDER, valueIfMissing);
201     }
202 
203     /**
204      * Returns the camera executor which CameraX will use to drive the camera stack.
205      *
206      * @see Builder#setCameraExecutor(Executor)
207      */
getCameraExecutor(@ullable Executor valueIfMissing)208     public @Nullable Executor getCameraExecutor(@Nullable Executor valueIfMissing) {
209         return mConfig.retrieveOption(OPTION_CAMERA_EXECUTOR, valueIfMissing);
210     }
211 
212     /**
213      * Returns the scheduling handler that CameraX will use internally for scheduling future tasks.
214      *
215      * @see Builder#setSchedulerHandler(Handler)
216      */
getSchedulerHandler(@ullable Handler valueIfMissing)217     public @Nullable Handler getSchedulerHandler(@Nullable Handler valueIfMissing) {
218         return mConfig.retrieveOption(OPTION_SCHEDULER_HANDLER, valueIfMissing);
219     }
220 
221     /**
222      * Returns the minimum logging level to be used for CameraX logs.
223      *
224      * @see Builder#setMinimumLoggingLevel(int)
225      */
getMinimumLoggingLevel()226     public int getMinimumLoggingLevel() {
227         return mConfig.retrieveOption(OPTION_MIN_LOGGING_LEVEL, Logger.DEFAULT_MIN_LOG_LEVEL);
228     }
229 
230     /**
231      * Returns the {@link CameraSelector} used to determine the available cameras.
232      *
233      * @see Builder#setAvailableCamerasLimiter(CameraSelector)
234      */
getAvailableCamerasLimiter( @ullable CameraSelector valueIfMissing)235     public @Nullable CameraSelector getAvailableCamerasLimiter(
236             @Nullable CameraSelector valueIfMissing) {
237         return mConfig.retrieveOption(OPTION_AVAILABLE_CAMERAS_LIMITER, valueIfMissing);
238     }
239 
240     /**
241      * Returns the camera open retry maximum timeout in milliseconds when in active resuming mode.
242      *
243      * <p>If this value is not set, -1L will be returned by default.
244      *
245      * @see Builder#setCameraOpenRetryMaxTimeoutInMillisWhileResuming(long)
246      */
getCameraOpenRetryMaxTimeoutInMillisWhileResuming()247     public long getCameraOpenRetryMaxTimeoutInMillisWhileResuming() {
248         return mConfig.retrieveOption(OPTION_CAMERA_OPEN_RETRY_MAX_TIMEOUT_IN_MILLIS_WHILE_RESUMING,
249                 DEFAULT_OPTION_CAMERA_OPEN_RETRY_MAX_TIMEOUT_IN_MILLIS_WHILE_RESUMING);
250     }
251 
252     /**
253      * Retrieves the {@link RetryPolicy} for the CameraProvider initialization. This policy
254      * determines whether to retry the CameraProvider initialization if it fails.
255      *
256      * @return The {@link RetryPolicy} to be used for the CameraProvider initialization. If not
257      * explicitly set, it defaults to {@link RetryPolicy#DEFAULT}.
258      *
259      * @see Builder#setCameraProviderInitRetryPolicy(RetryPolicy)
260      */
261     @ExperimentalRetryPolicy
getCameraProviderInitRetryPolicy()262     public @NonNull RetryPolicy getCameraProviderInitRetryPolicy() {
263         return Objects.requireNonNull(
264                 mConfig.retrieveOption(OPTION_CAMERA_PROVIDER_INIT_RETRY_POLICY,
265                         RetryPolicy.DEFAULT));
266     }
267 
268     /**
269      * Returns the quirk settings.
270      *
271      * <p>If this value is not set, a default quirk settings will be returned.
272      *
273      * @return the quirk settings.
274      *
275      * @see Builder#setQuirkSettings(QuirkSettings)
276      */
277     @RestrictTo(Scope.LIBRARY_GROUP)
getQuirkSettings()278     public @Nullable QuirkSettings getQuirkSettings() {
279         return mConfig.retrieveOption(OPTION_QUIRK_SETTINGS, null);
280     }
281 
282     /**
283      * Returns the config impl type.
284      *
285      * @return the config impl type.
286      *
287      * @see Builder#setConfigImplType(int)
288      */
289     @RestrictTo(Scope.LIBRARY_GROUP)
getConfigImplType()290     public @ImplType int getConfigImplType() {
291         return mConfig.retrieveOption(OPTION_CONFIG_IMPL_TYPE, CAMERAX_CONFIG_IMPL_TYPE_UNKNOWN);
292     }
293 
294     @RestrictTo(Scope.LIBRARY_GROUP)
295     @Override
getConfig()296     public @NonNull Config getConfig() {
297         return mConfig;
298     }
299 
300     /** A builder for generating {@link CameraXConfig} objects. */
301     @SuppressWarnings({"ObjectToString", "HiddenSuperclass"})
302     public static final class Builder
303             implements TargetConfig.Builder<CameraX, CameraXConfig.Builder> {
304 
305         private final MutableOptionsBundle mMutableConfig;
306 
307         /**
308          * Creates a new Builder object.
309          *
310          */
311         @RestrictTo(Scope.LIBRARY_GROUP)
Builder()312         public Builder() {
313             this(MutableOptionsBundle.create());
314         }
315 
Builder(MutableOptionsBundle mutableConfig)316         private Builder(MutableOptionsBundle mutableConfig) {
317             mMutableConfig = mutableConfig;
318 
319             Class<?> oldConfigClass =
320                     mutableConfig.retrieveOption(TargetConfig.OPTION_TARGET_CLASS, null);
321             if (oldConfigClass != null && !oldConfigClass.equals(CameraX.class)) {
322                 throw new IllegalArgumentException(
323                         "Invalid target class configuration for "
324                                 + CameraXConfig.Builder.this
325                                 + ": "
326                                 + oldConfigClass);
327             }
328 
329             setTargetClass(CameraX.class);
330         }
331 
332         /**
333          * Generates a Builder from another {@link CameraXConfig} object
334          *
335          * @param configuration An immutable configuration to pre-populate this builder.
336          * @return The new Builder.
337          */
fromConfig(@onNull CameraXConfig configuration)338         public static @NonNull Builder fromConfig(@NonNull CameraXConfig configuration) {
339             return new Builder(MutableOptionsBundle.from(configuration));
340         }
341 
342         /**
343          * Sets the {@link CameraFactory} implementation for the application.
344          *
345          */
346         @RestrictTo(Scope.LIBRARY_GROUP)
setCameraFactoryProvider( CameraFactory.@onNull Provider cameraFactory)347         public @NonNull Builder setCameraFactoryProvider(
348                 CameraFactory.@NonNull Provider cameraFactory) {
349             getMutableConfig().insertOption(OPTION_CAMERA_FACTORY_PROVIDER, cameraFactory);
350             return this;
351         }
352 
353         /**
354          * Sets the {@link CameraDeviceSurfaceManager} implementation for the application.
355          *
356          */
357         @RestrictTo(Scope.LIBRARY_GROUP)
setDeviceSurfaceManagerProvider( CameraDeviceSurfaceManager.@onNull Provider surfaceManagerProvider)358         public @NonNull Builder setDeviceSurfaceManagerProvider(
359                 CameraDeviceSurfaceManager.@NonNull Provider surfaceManagerProvider) {
360             getMutableConfig().insertOption(OPTION_DEVICE_SURFACE_MANAGER_PROVIDER,
361                     surfaceManagerProvider);
362             return this;
363         }
364 
365         /**
366          * Sets the {@link UseCaseConfigFactory} implementation for the application.
367          *
368          * <p>This factory should produce all default configurations for the application's use
369          * cases.
370          *
371          */
372         @RestrictTo(Scope.LIBRARY_GROUP)
setUseCaseConfigFactoryProvider( UseCaseConfigFactory.@onNull Provider configFactoryProvider)373         public @NonNull Builder setUseCaseConfigFactoryProvider(
374                 UseCaseConfigFactory.@NonNull Provider configFactoryProvider) {
375             getMutableConfig().insertOption(OPTION_USECASE_CONFIG_FACTORY_PROVIDER,
376                     configFactoryProvider);
377             return this;
378         }
379 
380         /**
381          * Sets an executor which CameraX will use to drive the camera stack.
382          *
383          * <p>This option can be used to override the default internal executor created by
384          * CameraX, and will be used by the implementation to drive all cameras.
385          *
386          * <p>It is not necessary to set an executor for normal use, and should only be used in
387          * applications with very specific threading requirements. If not set, CameraX will
388          * create and use an optimized default internal executor.
389          */
setCameraExecutor(@onNull Executor executor)390         public @NonNull Builder setCameraExecutor(@NonNull Executor executor) {
391             getMutableConfig().insertOption(OPTION_CAMERA_EXECUTOR, executor);
392             return this;
393         }
394 
395         /**
396          * Sets a handler that CameraX will use internally for scheduling future tasks.
397          *
398          * <p>This scheduler may also be used for legacy APIs which require a {@link Handler}. Tasks
399          * that are scheduled with this handler will always be executed by the camera executor. No
400          * business logic will be executed directly by this handler.
401          *
402          * <p>It is not necessary to set a scheduler handler for normal use, and should only be
403          * used in applications with very specific threading requirements. If not set, CameraX
404          * will create and use an optimized default internal handler.
405          *
406          * @see #setCameraExecutor(Executor)
407          */
setSchedulerHandler(@onNull Handler handler)408         public @NonNull Builder setSchedulerHandler(@NonNull Handler handler) {
409             getMutableConfig().insertOption(OPTION_SCHEDULER_HANDLER, handler);
410             return this;
411         }
412 
413         /**
414          * Sets the minimum logging level to be used for CameraX logs.
415          * <p>
416          * The logging level should be one of the following: {@link Log#DEBUG}, {@link Log#INFO},
417          * {@link Log#WARN} or {@link Log#ERROR}.
418          * <p>
419          * When not specified, the default minimum logging level used inside CameraX is
420          * {@link Log#DEBUG}.
421          * <p>
422          * For apps that want to reduce the logs produced by CameraX, set it to {@link Log#ERROR}
423          * to avoid all logs except for error.
424          *
425          * @param logLevel The minimum logging level, which should be {@link Log#DEBUG},
426          *                 {@link Log#INFO}, {@link Log#WARN} or {@link Log#ERROR}.
427          * @return This {@link Builder} instance.
428          */
setMinimumLoggingLevel( @ntRangefrom = Log.DEBUG, to = Log.ERROR) int logLevel)429         public @NonNull Builder setMinimumLoggingLevel(
430                 @IntRange(from = Log.DEBUG, to = Log.ERROR) int logLevel) {
431             getMutableConfig().insertOption(OPTION_MIN_LOGGING_LEVEL, logLevel);
432             return this;
433         }
434 
435         /**
436          * Sets a {@link CameraSelector} to determine the available cameras, thus defining which
437          * cameras can be used in the application.
438          *
439          * <p>Only cameras selected by this CameraSelector can be used in the application. If the
440          * application binds use cases with a CameraSelector that selects an unavailable camera,
441          * an {@link IllegalArgumentException} will be thrown.
442          *
443          * <p>This configuration can help CameraX optimize the latency of CameraX initialization.
444          * The tasks CameraX initialization performs include enumerating cameras, querying
445          * camera characteristics and retrieving properties in preparation for resolution
446          * determination. On some low end devices, these tasks could take a significant amount of
447          * time. Using this method can avoid the initialization of unnecessary cameras and speed
448          * up the time for camera start-up. For example, if the application uses only back facing
449          * cameras, it can set this configuration with {@link CameraSelector#DEFAULT_BACK_CAMERA}
450          * and then CameraX will avoid initializing front facing cameras to reduce the latency.
451          */
setAvailableCamerasLimiter( @onNull CameraSelector availableCameraSelector)452         public @NonNull Builder setAvailableCamerasLimiter(
453                 @NonNull CameraSelector availableCameraSelector) {
454             getMutableConfig().insertOption(OPTION_AVAILABLE_CAMERAS_LIMITER,
455                     availableCameraSelector);
456             return this;
457         }
458 
459         /**
460          * Sets the camera open retry maximum timeout in milliseconds. This is only needed when
461          * users don't want to retry camera opening for a long time.
462          *
463          * <p>When {@link androidx.lifecycle.LifecycleOwner} is in ON_RESUME state, CameraX will
464          * actively retry opening the camera periodically to resume, until there is
465          * non-recoverable errors happening and then move to pending open state waiting for the
466          * next camera available after timeout.
467          *
468          * <p>When in active resuming mode, it will periodically retry opening the
469          * camera regardless of the camera availability.
470          * Elapsed time <= 2 minutes -> retry once per 1 second.
471          * Elapsed time 2 to 5 minutes -> retry once per 2 seconds.
472          * Elapsed time > 5 minutes -> retry once per 4 seconds.
473          * Retry will stop after 30 minutes.
474          *
475          * <p>When not in active resuming mode, the camera will be attempted to be opened every
476          * 700ms for 10 seconds. This value cannot currently be changed.
477          *
478          * @param maxTimeoutInMillis The max timeout in milliseconds.
479          * @return this builder.
480          */
setCameraOpenRetryMaxTimeoutInMillisWhileResuming( long maxTimeoutInMillis)481         public @NonNull Builder setCameraOpenRetryMaxTimeoutInMillisWhileResuming(
482                 long maxTimeoutInMillis) {
483             getMutableConfig().insertOption(
484                     OPTION_CAMERA_OPEN_RETRY_MAX_TIMEOUT_IN_MILLIS_WHILE_RESUMING,
485                     maxTimeoutInMillis);
486             return this;
487         }
488 
489         /**
490          * Sets the {@link RetryPolicy} for the CameraProvider initialization. This policy
491          * determines whether to retry the CameraProvider initialization if it fails.
492          *
493          * <p>If not set, a default retry policy {@link RetryPolicy#DEFAULT} will be applied.
494          *
495          * @param retryPolicy The {@link RetryPolicy} to use for retrying the CameraProvider
496          *                    initialization.
497          * @return this builder.
498          */
499         @ExperimentalRetryPolicy
setCameraProviderInitRetryPolicy(@onNull RetryPolicy retryPolicy)500         public @NonNull Builder setCameraProviderInitRetryPolicy(@NonNull RetryPolicy retryPolicy) {
501             getMutableConfig().insertOption(
502                     OPTION_CAMERA_PROVIDER_INIT_RETRY_POLICY,
503                     retryPolicy);
504             return this;
505         }
506 
507         /**
508          * Sets the quirk settings.
509          *
510          * @param quirkSettings the quirk settings.
511          * @return this builder.
512          */
513         @RestrictTo(Scope.LIBRARY_GROUP)
setQuirkSettings(@onNull QuirkSettings quirkSettings)514         public @NonNull Builder setQuirkSettings(@NonNull QuirkSettings quirkSettings) {
515             getMutableConfig().insertOption(OPTION_QUIRK_SETTINGS, quirkSettings);
516             return this;
517         }
518 
getMutableConfig()519         private @NonNull MutableConfig getMutableConfig() {
520             return mMutableConfig;
521         }
522 
523         /**
524          * Builds an immutable {@link CameraXConfig} from the current state.
525          *
526          * @return A {@link CameraXConfig} populated with the current state.
527          */
build()528         public @NonNull CameraXConfig build() {
529             return new CameraXConfig(OptionsBundle.from(mMutableConfig));
530         }
531 
532         // Implementations of TargetConfig.Builder default methods
533 
534         @RestrictTo(Scope.LIBRARY_GROUP)
535         @Override
setTargetClass(@onNull Class<CameraX> targetClass)536         public @NonNull Builder setTargetClass(@NonNull Class<CameraX> targetClass) {
537             getMutableConfig().insertOption(OPTION_TARGET_CLASS, targetClass);
538 
539             // If no name is set yet, then generate a unique name
540             if (null == getMutableConfig().retrieveOption(OPTION_TARGET_NAME, null)) {
541                 String targetName = targetClass.getCanonicalName() + "-" + UUID.randomUUID();
542                 setTargetName(targetName);
543             }
544 
545             return this;
546         }
547 
548         @RestrictTo(Scope.LIBRARY_GROUP)
549         @Override
setTargetName(@onNull String targetName)550         public @NonNull Builder setTargetName(@NonNull String targetName) {
551             getMutableConfig().insertOption(OPTION_TARGET_NAME, targetName);
552             return this;
553         }
554 
555         /**
556          * Sets the config impl type.
557          *
558          * <p>The available impl types are {@link #CAMERAX_CONFIG_IMPL_TYPE_CAMERA_CAMERA2},
559          * {@link #CAMERAX_CONFIG_IMPL_TYPE_PIPE} and {@link #CAMERAX_CONFIG_IMPL_TYPE_UNKNOWN}.
560          */
561         @RestrictTo(Scope.LIBRARY_GROUP)
setConfigImplType(@mplType int configImplType)562         public @NonNull Builder setConfigImplType(@ImplType int configImplType) {
563             getMutableConfig().insertOption(OPTION_CONFIG_IMPL_TYPE, configImplType);
564             return this;
565         }
566     }
567 }
568