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