1 /*
2  * Copyright 2021 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 package androidx.camera.camera2.pipe.integration.interop
17 
18 import android.hardware.camera2.CaptureRequest
19 import androidx.annotation.RestrictTo
20 import androidx.camera.camera2.pipe.integration.impl.CAPTURE_REQUEST_ID_STEM
21 import androidx.camera.camera2.pipe.integration.impl.createCaptureRequestOption
22 import androidx.camera.core.ExtendableBuilder
23 import androidx.camera.core.impl.Config
24 import androidx.camera.core.impl.MutableConfig
25 import androidx.camera.core.impl.MutableOptionsBundle
26 import androidx.camera.core.impl.OptionsBundle
27 import androidx.camera.core.impl.ReadableConfig
28 
29 /**
30  * A bundle of Camera2 capture request options.
31  *
32  * @constructor Creates a CaptureRequestOptions for reading Camera2 capture request options from the
33  *   given config.
34  * @property config The config that potentially contains Camera2 capture request options.
35  */
36 @ExperimentalCamera2Interop
37 public open class CaptureRequestOptions
38 private constructor(private val config: Config, @Suppress("UNUSED_PARAMETER") unused: Boolean) :
39     ReadableConfig {
40 
41     internal constructor(config: Config) : this(config, false)
42 
43     /**
44      * Returns a value for the given [CaptureRequest.Key] or null if it hasn't been set.
45      *
46      * @param key The key to retrieve.
47      * @param ValueT The type of the value.
48      * @return The stored value or null if the value does not exist in this configuration.
49      */
getCaptureRequestOptionnull50     public open fun <ValueT> getCaptureRequestOption(key: CaptureRequest.Key<ValueT>): ValueT? {
51         // Type should have been only set via Builder#setCaptureRequestOption()
52         @Suppress("UNCHECKED_CAST")
53         val opt = key.createCaptureRequestOption() as Config.Option<ValueT>
54         return config.retrieveOption(opt, null)
55     }
56 
57     /**
58      * Returns a value for the given [CaptureRequest.Key].
59      *
60      * @param key The key to retrieve.
61      * @param valueIfMissing The value to return if this configuration option has not been set.
62      * @param ValueT The type of the value.
63      * @return The stored value or `valueIfMissing` if the value does not exist in this
64      *   configuration.
65      */
getCaptureRequestOptionnull66     internal fun <ValueT> getCaptureRequestOption(
67         key: CaptureRequest.Key<ValueT>,
68         valueIfMissing: ValueT?
69     ): ValueT? {
70         // Type should have been only set via Builder#setCaptureRequestOption()
71         @Suppress("UNCHECKED_CAST")
72         val opt = key.createCaptureRequestOption() as Config.Option<ValueT>
73         return config.retrieveOption(opt, valueIfMissing)
74     }
75 
76     /** Returns the [Config] object associated with this [CaptureRequestOptions]. */
77     @RestrictTo(RestrictTo.Scope.LIBRARY)
getConfignull78     override fun getConfig(): Config {
79         return config
80     }
81 
82     /** Builder for creating [CaptureRequestOptions] instance. */
83     public class Builder : ExtendableBuilder<CaptureRequestOptions?> {
84         private val mutableOptionsBundle = MutableOptionsBundle.create()
85 
86         public companion object {
87             /**
88              * Generates a Builder from another Config object.
89              *
90              * @param config An immutable configuration to pre-populate this builder.
91              * @return The new Builder.
92              */
93             @JvmStatic
94             @RestrictTo(RestrictTo.Scope.LIBRARY)
fromnull95             public fun from(config: Config): Builder {
96                 val bundleBuilder = Builder()
97                 config.findOptions(CAPTURE_REQUEST_ID_STEM) {
98                     // Erase the type of the option. Capture request options should only be
99                     // set via Camera2Interop so that the type of the key and value should
100                     // always match.
101                     @Suppress("UNCHECKED_CAST") val objectOpt = it as Config.Option<Any>
102                     bundleBuilder.mutableConfig.insertOption(
103                         objectOpt,
104                         config.getOptionPriority(objectOpt),
105                         config.retrieveOption(objectOpt)
106                     )
107                     true
108                 }
109                 return bundleBuilder
110             }
111         }
112 
113         /** {@inheritDoc} */
114         @RestrictTo(RestrictTo.Scope.LIBRARY)
getMutableConfignull115         override fun getMutableConfig(): MutableConfig {
116             return mutableOptionsBundle
117         }
118 
119         /** Inserts new capture request option with specific [CaptureRequest.Key] setting. */
setCaptureRequestOptionnull120         public fun <ValueT> setCaptureRequestOption(
121             key: CaptureRequest.Key<ValueT>,
122             value: ValueT
123         ): Builder {
124             val opt = key.createCaptureRequestOption()
125             mutableOptionsBundle.insertOption(opt, value)
126             return this
127         }
128 
129         /** Removes a capture request option with specific [CaptureRequest.Key] setting. */
clearCaptureRequestOptionnull130         public fun <ValueT> clearCaptureRequestOption(key: CaptureRequest.Key<ValueT>): Builder {
131             val opt = key.createCaptureRequestOption()
132             mutableOptionsBundle.removeOption(opt)
133             return this
134         }
135 
136         /**
137          * Builds an immutable [CaptureRequestOptions] from the current state.
138          *
139          * @return A [CaptureRequestOptions] populated with the current state.
140          */
buildnull141         override fun build(): CaptureRequestOptions {
142             return CaptureRequestOptions(OptionsBundle.from(mutableOptionsBundle))
143         }
144     }
145 }
146