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.camera2.impl; 18 19 import android.hardware.camera2.CameraCaptureSession; 20 import android.hardware.camera2.CameraDevice; 21 import android.hardware.camera2.CaptureRequest; 22 23 import androidx.annotation.OptIn; 24 import androidx.annotation.RestrictTo; 25 import androidx.annotation.RestrictTo.Scope; 26 import androidx.camera.camera2.interop.CaptureRequestOptions; 27 import androidx.camera.camera2.interop.ExperimentalCamera2Interop; 28 import androidx.camera.core.ExtendableBuilder; 29 import androidx.camera.core.impl.Config; 30 import androidx.camera.core.impl.MutableConfig; 31 import androidx.camera.core.impl.MutableOptionsBundle; 32 import androidx.camera.core.impl.OptionsBundle; 33 34 import org.jspecify.annotations.NonNull; 35 import org.jspecify.annotations.Nullable; 36 37 /** 38 * Internal shared implementation details for camera 2 interop. 39 */ 40 @OptIn(markerClass = ExperimentalCamera2Interop.class) 41 public final class Camera2ImplConfig extends CaptureRequestOptions { 42 43 @RestrictTo(Scope.LIBRARY) 44 public static final String CAPTURE_REQUEST_ID_STEM = "camera2.captureRequest.option."; 45 46 // Option Declarations: 47 // ********************************************************************************************* 48 49 @RestrictTo(Scope.LIBRARY) 50 public static final Config.Option<Integer> TEMPLATE_TYPE_OPTION = 51 Option.create("camera2.captureRequest.templateType", int.class); 52 @RestrictTo(Scope.LIBRARY) 53 public static final Config.Option<Long> STREAM_USE_CASE_OPTION = 54 Option.create("camera2.cameraCaptureSession.streamUseCase", long.class); 55 @RestrictTo(Scope.LIBRARY) 56 public static final Option<CameraDevice.StateCallback> DEVICE_STATE_CALLBACK_OPTION = 57 Option.create("camera2.cameraDevice.stateCallback", CameraDevice.StateCallback.class); 58 @RestrictTo(Scope.LIBRARY) 59 public static final Option<CameraCaptureSession.StateCallback> SESSION_STATE_CALLBACK_OPTION = 60 Option.create( 61 "camera2.cameraCaptureSession.stateCallback", 62 CameraCaptureSession.StateCallback.class); 63 @RestrictTo(Scope.LIBRARY) 64 public static final Option<CameraCaptureSession.CaptureCallback> 65 SESSION_CAPTURE_CALLBACK_OPTION = 66 Option.create("camera2.cameraCaptureSession.captureCallback", 67 CameraCaptureSession.CaptureCallback.class); 68 @RestrictTo(Scope.LIBRARY) 69 public static final Option<Object> CAPTURE_REQUEST_TAG_OPTION = Option.create( 70 "camera2.captureRequest.tag", Object.class); 71 72 @RestrictTo(Scope.LIBRARY) 73 public static final Option<String> SESSION_PHYSICAL_CAMERA_ID_OPTION = Option.create( 74 "camera2.cameraCaptureSession.physicalCameraId", String.class); 75 76 // ********************************************************************************************* 77 78 /** 79 * Creates a Camera2ImplConfig for reading Camera2 options from the given config. 80 * 81 * @param config The config that potentially contains Camera2 options. 82 */ Camera2ImplConfig(@onNull Config config)83 public Camera2ImplConfig(@NonNull Config config) { 84 super(config); 85 } 86 87 // Unfortunately, we can't get the Class<T> from the CaptureRequest.Key, so we're forced to 88 // erase the type. This shouldn't be a problem as long as we are only using these options 89 // within the Camera2ImplConfig and Camera2ImplConfig.Builder classes. 90 91 @RestrictTo(Scope.LIBRARY) createCaptureRequestOption( CaptureRequest.@onNull Key<?> key)92 public static @NonNull Option<Object> createCaptureRequestOption( 93 CaptureRequest.@NonNull Key<?> key) { 94 return Option.create(CAPTURE_REQUEST_ID_STEM + key.getName(), Object.class, key); 95 } 96 97 /** 98 * Returns all capture request options contained in this configuration. 99 * 100 */ 101 @RestrictTo(Scope.LIBRARY) getCaptureRequestOptions()102 public @NonNull CaptureRequestOptions getCaptureRequestOptions() { 103 return CaptureRequestOptions.Builder.from(getConfig()).build(); 104 } 105 106 /** 107 * Returns a CameraDevice template on the given configuration. Requires API 33 or above. 108 * 109 * <p>See {@link android.hardware.camera2.CameraMetadata} for valid stream use cases. 110 * See {@link android.hardware.camera2.params.OutputConfiguration} to see how 111 * camera2 framework uses this. 112 * 113 * @param valueIfMissing The value to return if this configuration option has not been set. 114 * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this 115 * configuration. 116 */ getStreamUseCase(long valueIfMissing)117 public long getStreamUseCase(long valueIfMissing) { 118 return getConfig().retrieveOption(STREAM_USE_CASE_OPTION, valueIfMissing); 119 } 120 121 /** 122 * Returns the CameraDevice template from the given configuration. 123 * 124 * <p>See {@link CameraDevice} for valid template types. For example, {@link 125 * CameraDevice#TEMPLATE_PREVIEW}. 126 * 127 * @param valueIfMissing The value to return if this configuration option has not been set. 128 * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this 129 * configuration. 130 */ getCaptureRequestTemplate(int valueIfMissing)131 public int getCaptureRequestTemplate(int valueIfMissing) { 132 return getConfig().retrieveOption(TEMPLATE_TYPE_OPTION, valueIfMissing); 133 } 134 135 /** 136 * Returns the stored {@link CameraDevice.StateCallback}. 137 * 138 * @param valueIfMissing The value to return if this configuration option has not been set. 139 * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this 140 * configuration. 141 */ getDeviceStateCallback( CameraDevice.@ullable StateCallback valueIfMissing)142 public CameraDevice.@Nullable StateCallback getDeviceStateCallback( 143 CameraDevice.@Nullable StateCallback valueIfMissing) { 144 return getConfig().retrieveOption(DEVICE_STATE_CALLBACK_OPTION, valueIfMissing); 145 } 146 147 148 /** 149 * Returns the stored {@link CameraCaptureSession.StateCallback}. 150 * 151 * @param valueIfMissing The value to return if this configuration option has not been set. 152 * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this 153 * configuration. 154 */ getSessionStateCallback( CameraCaptureSession.@ullable StateCallback valueIfMissing)155 public CameraCaptureSession.@Nullable StateCallback getSessionStateCallback( 156 CameraCaptureSession.@Nullable StateCallback valueIfMissing) { 157 return getConfig().retrieveOption(SESSION_STATE_CALLBACK_OPTION, valueIfMissing); 158 } 159 160 /** 161 * Returns the stored {@link CameraCaptureSession.CaptureCallback}. 162 * 163 * @param valueIfMissing The value to return if this configuration option has not been set. 164 * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this 165 * configuration. 166 */ getSessionCaptureCallback( CameraCaptureSession.@ullable CaptureCallback valueIfMissing)167 public CameraCaptureSession.@Nullable CaptureCallback getSessionCaptureCallback( 168 CameraCaptureSession.@Nullable CaptureCallback valueIfMissing) { 169 return getConfig().retrieveOption(SESSION_CAPTURE_CALLBACK_OPTION, valueIfMissing); 170 } 171 172 /** 173 * Returns the capture request tag. 174 * 175 * @param valueIfMissing The value to return if this configuration option has not been set. 176 * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this 177 * configuration. 178 */ getCaptureRequestTag(@ullable Object valueIfMissing)179 public @Nullable Object getCaptureRequestTag(@Nullable Object valueIfMissing) { 180 return getConfig().retrieveOption(CAPTURE_REQUEST_TAG_OPTION, valueIfMissing); 181 } 182 183 /** 184 * Returns the physical camera ID. 185 * 186 * @param valueIfMissing The value to return if this configuration option has not been set. 187 * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this 188 * configuration. 189 */ getPhysicalCameraId(@ullable String valueIfMissing)190 public @Nullable String getPhysicalCameraId(@Nullable String valueIfMissing) { 191 return getConfig().retrieveOption(SESSION_PHYSICAL_CAMERA_ID_OPTION, valueIfMissing); 192 } 193 194 /** 195 * Builder for creating {@link Camera2ImplConfig} instance. 196 * 197 * <p>Use {@link Camera2ImplConfig.Builder} for creating {@link Config} which contains 198 * camera2 options only. And use 199 * {@link androidx.camera.camera2.interop.Camera2Interop.Extender} to add Camera2 options on 200 * existing other {@link 201 * ExtendableBuilder}. 202 */ 203 public static final class Builder implements ExtendableBuilder<Camera2ImplConfig> { 204 205 private final MutableOptionsBundle mMutableOptionsBundle = MutableOptionsBundle.create(); 206 207 @Override getMutableConfig()208 public @NonNull MutableConfig getMutableConfig() { 209 return mMutableOptionsBundle; 210 } 211 212 /** 213 * Inserts new capture request option with specific {@link CaptureRequest.Key} setting. 214 */ setCaptureRequestOption( CaptureRequest.@onNull Key<ValueT> key, @NonNull ValueT value)215 public <ValueT> Camera2ImplConfig.@NonNull Builder setCaptureRequestOption( 216 CaptureRequest.@NonNull Key<ValueT> key, @NonNull ValueT value) { 217 Option<Object> opt = Camera2ImplConfig.createCaptureRequestOption(key); 218 mMutableOptionsBundle.insertOption(opt, value); 219 return this; 220 } 221 222 /** 223 * Inserts new capture request option with specific {@link CaptureRequest.Key} setting and 224 * {@link OptionPriority}. 225 */ setCaptureRequestOptionWithPriority( CaptureRequest.@onNull Key<ValueT> key, @NonNull ValueT value, @NonNull OptionPriority priority)226 public <ValueT> @NonNull Builder setCaptureRequestOptionWithPriority( 227 CaptureRequest.@NonNull Key<ValueT> key, @NonNull ValueT value, 228 @NonNull OptionPriority priority) { 229 Option<Object> opt = Camera2ImplConfig.createCaptureRequestOption(key); 230 mMutableOptionsBundle.insertOption(opt, priority, value); 231 return this; 232 } 233 234 /** Inserts options from other {@link Config} object. */ insertAllOptions(@onNull Config config)235 public Camera2ImplConfig.@NonNull Builder insertAllOptions(@NonNull Config config) { 236 insertAllOptions(config, OptionPriority.OPTIONAL); 237 return this; 238 } 239 240 /** Inserts options from other {@link Config} object with the given option priority. */ insertAllOptions(@onNull Config config, @NonNull OptionPriority optionPriority)241 public Camera2ImplConfig.@NonNull Builder insertAllOptions(@NonNull Config config, 242 @NonNull OptionPriority optionPriority) { 243 for (Option<?> option : config.listOptions()) { 244 @SuppressWarnings("unchecked") // Options/values are being copied directly 245 Option<Object> objectOpt = (Option<Object>) option; 246 mMutableOptionsBundle.insertOption(objectOpt, optionPriority, 247 config.retrieveOption(objectOpt)); 248 } 249 return this; 250 } 251 252 /** 253 * Builds an immutable {@link Camera2ImplConfig} from the current state. 254 * 255 * @return A {@link Camera2ImplConfig} populated with the current state. 256 */ 257 @Override build()258 public @NonNull Camera2ImplConfig build() { 259 return new Camera2ImplConfig(OptionsBundle.from(mMutableOptionsBundle)); 260 } 261 } 262 } 263