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.interop; 18 19 import android.hardware.camera2.CameraCharacteristics; 20 import android.util.Pair; 21 22 import androidx.annotation.RestrictTo; 23 import androidx.annotation.RestrictTo.Scope; 24 import androidx.camera.camera2.internal.Camera2CameraInfoImpl; 25 import androidx.camera.camera2.internal.Camera2PhysicalCameraInfoImpl; 26 import androidx.camera.core.CameraInfo; 27 import androidx.camera.core.CameraSelector; 28 import androidx.camera.core.impl.AdapterCameraInfo; 29 import androidx.camera.core.impl.CameraInfoInternal; 30 import androidx.camera.core.impl.SessionProcessor; 31 import androidx.core.util.Preconditions; 32 33 import org.jspecify.annotations.NonNull; 34 import org.jspecify.annotations.Nullable; 35 36 import java.util.Collections; 37 import java.util.List; 38 import java.util.Map; 39 40 /** 41 * An interface for retrieving Camera2-related camera information. 42 */ 43 @ExperimentalCamera2Interop 44 public final class Camera2CameraInfo { 45 private static final String TAG = "Camera2CameraInfo"; 46 47 private @Nullable Camera2CameraInfoImpl mCamera2CameraInfoImpl; 48 49 // TODO: clean up by passing in CameraId, CameraCharacteristicCompat and CameraManager 50 // instead of concrete implementation. 51 private @Nullable Camera2PhysicalCameraInfoImpl mCamera2PhysicalCameraInfo; 52 private @Nullable List<Pair<CameraCharacteristics.Key, Object>> mExtensionsSpecificChars; 53 /** 54 * Creates a new logical camera information with Camera2 implementation. 55 * 56 */ 57 @RestrictTo(Scope.LIBRARY) Camera2CameraInfo(@onNull Camera2CameraInfoImpl camera2CameraInfoImpl)58 public Camera2CameraInfo(@NonNull Camera2CameraInfoImpl camera2CameraInfoImpl) { 59 mCamera2CameraInfoImpl = camera2CameraInfoImpl; 60 } 61 62 /** 63 * Creates a new physical camera information with Camera2 implementation. 64 */ 65 @RestrictTo(Scope.LIBRARY) Camera2CameraInfo(@onNull Camera2PhysicalCameraInfoImpl camera2PhysicalCameraInfo)66 public Camera2CameraInfo(@NonNull Camera2PhysicalCameraInfoImpl camera2PhysicalCameraInfo) { 67 mCamera2PhysicalCameraInfo = camera2PhysicalCameraInfo; 68 } 69 Camera2CameraInfo(@onNull Camera2CameraInfoImpl camera2CameraInfoImpl, List<Pair<CameraCharacteristics.Key, Object>> extensionsSpecificChars)70 private Camera2CameraInfo(@NonNull Camera2CameraInfoImpl camera2CameraInfoImpl, 71 List<Pair<CameraCharacteristics.Key, Object>> extensionsSpecificChars) { 72 mCamera2CameraInfoImpl = camera2CameraInfoImpl; 73 mExtensionsSpecificChars = extensionsSpecificChars; 74 } 75 76 /** 77 * Gets the {@link Camera2CameraInfo} from a {@link CameraInfo}. 78 * 79 * <p>If the {@link CameraInfo} is retrieved by an Extensions-enabled {@link CameraSelector}, 80 * calling {@link #getCameraCharacteristic(CameraCharacteristics.Key)} will return any available 81 * Extensions-specific characteristics if exists. 82 * 83 * @param cameraInfo The {@link CameraInfo} to get from. 84 * @return The camera information with Camera2 implementation. 85 * @throws IllegalArgumentException if the camera info does not contain the camera2 information 86 * (e.g., if CameraX was not initialized with a 87 * {@link androidx.camera.camera2.Camera2Config}). 88 */ from(@onNull CameraInfo cameraInfo)89 public static @NonNull Camera2CameraInfo from(@NonNull CameraInfo cameraInfo) { 90 if (cameraInfo instanceof Camera2PhysicalCameraInfoImpl) { 91 return ((Camera2PhysicalCameraInfoImpl) cameraInfo).getCamera2CameraInfo(); 92 } 93 94 CameraInfoInternal cameraInfoImpl = 95 ((CameraInfoInternal) cameraInfo).getImplementation(); 96 Preconditions.checkArgument(cameraInfoImpl instanceof Camera2CameraInfoImpl, 97 "CameraInfo doesn't contain Camera2 implementation."); 98 Camera2CameraInfo camera2CameraInfo = 99 ((Camera2CameraInfoImpl) cameraInfoImpl).getCamera2CameraInfo(); 100 if (cameraInfo instanceof AdapterCameraInfo) { 101 SessionProcessor sessionProcessor = 102 ((AdapterCameraInfo) cameraInfo).getSessionProcessor(); 103 if (sessionProcessor != null) { 104 camera2CameraInfo = new Camera2CameraInfo( 105 camera2CameraInfo.mCamera2CameraInfoImpl, 106 sessionProcessor.getAvailableCharacteristicsKeyValues() 107 ); 108 } 109 } 110 return camera2CameraInfo; 111 } 112 113 /** 114 * Gets the string camera ID. 115 * 116 * <p>The camera ID is the same as the camera ID that would be obtained from 117 * {@link android.hardware.camera2.CameraManager#getCameraIdList()}. The ID that is retrieved 118 * is not static and can change depending on the current internal configuration of the 119 * {@link androidx.camera.core.Camera} from which the CameraInfo was retrieved. 120 * 121 * The Camera is a logical camera which can be backed by multiple 122 * {@link android.hardware.camera2.CameraDevice}. However, only one CameraDevice is active at 123 * one time. When the CameraDevice changes then the camera id will change. 124 * 125 * @return the camera ID. 126 * @throws IllegalStateException if the camera info does not contain the camera 2 camera ID 127 * (e.g., if CameraX was not initialized with a 128 * {@link androidx.camera.camera2.Camera2Config}). 129 */ getCameraId()130 public @NonNull String getCameraId() { 131 if (mCamera2PhysicalCameraInfo != null) { 132 return mCamera2PhysicalCameraInfo.getCameraId(); 133 } 134 return mCamera2CameraInfoImpl.getCameraId(); 135 } 136 137 /** 138 * Gets a camera characteristic value. 139 * 140 * <p>The characteristic value is the same as the value in the {@link CameraCharacteristics} 141 * that would be obtained from 142 * {@link android.hardware.camera2.CameraManager#getCameraCharacteristics(String)}. 143 * 144 * @param <T> The type of the characteristic value. 145 * @param key The {@link CameraCharacteristics.Key} of the characteristic. 146 * @return the value of the characteristic. 147 */ 148 @SuppressWarnings("unchecked") getCameraCharacteristic(CameraCharacteristics.@onNull Key<T> key)149 public <T> @Nullable T getCameraCharacteristic(CameraCharacteristics.@NonNull Key<T> key) { 150 if (mCamera2PhysicalCameraInfo != null) { 151 return mCamera2PhysicalCameraInfo.getCameraCharacteristicsCompat().get(key); 152 } 153 154 if (mExtensionsSpecificChars != null) { 155 for (Pair<CameraCharacteristics.Key, Object> pair : mExtensionsSpecificChars) { 156 if (pair.first.equals(key)) { 157 return (T) pair.second; 158 } 159 } 160 } 161 return mCamera2CameraInfoImpl.getCameraCharacteristicsCompat().get(key); 162 } 163 164 /** 165 * Returns the {@link CameraCharacteristics} for this camera. 166 * 167 * <p>The CameraCharacteristics will be the ones that would be obtained by 168 * {@link android.hardware.camera2.CameraManager#getCameraCharacteristics(String)}. The 169 * CameraCharacteristics that are retrieved are not static and can change depending on the 170 * current internal configuration of the camera. 171 * 172 * @param cameraInfo The {@link CameraInfo} to extract the CameraCharacteristics from. 173 * @throws IllegalStateException if the camera info does not contain the camera 2 174 * characteristics(e.g., if CameraX was not initialized with a 175 * {@link androidx.camera.camera2.Camera2Config}). 176 */ 177 // TODO: Hidden until new extensions API released. 178 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) extractCameraCharacteristics( @onNull CameraInfo cameraInfo)179 public static @NonNull CameraCharacteristics extractCameraCharacteristics( 180 @NonNull CameraInfo cameraInfo) { 181 if (cameraInfo instanceof Camera2PhysicalCameraInfoImpl) { 182 return ((Camera2PhysicalCameraInfoImpl) cameraInfo) 183 .getCameraCharacteristicsCompat() 184 .toCameraCharacteristics(); 185 } 186 187 CameraInfoInternal cameraInfoImpl = ((CameraInfoInternal) cameraInfo).getImplementation(); 188 Preconditions.checkState(cameraInfoImpl instanceof Camera2CameraInfoImpl, 189 "CameraInfo does not contain any Camera2 information."); 190 Camera2CameraInfoImpl impl = (Camera2CameraInfoImpl) cameraInfoImpl; 191 return impl.getCameraCharacteristicsCompat().toCameraCharacteristics(); 192 } 193 194 /** 195 * Returns a map consisting of the camera ids and the {@link CameraCharacteristics}s. 196 * 197 * <p>For every camera, the map contains at least the CameraCharacteristics for the camera id. 198 * If the camera is logical camera, it will also contain associated physical camera ids and 199 * their CameraCharacteristics. 200 * 201 */ 202 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) getCameraCharacteristicsMap()203 public @NonNull Map<String, CameraCharacteristics> getCameraCharacteristicsMap() { 204 if (mCamera2PhysicalCameraInfo != null) { 205 return Collections.emptyMap(); 206 } 207 return mCamera2CameraInfoImpl.getCameraCharacteristicsMap(); 208 } 209 } 210