1 /* 2 * Copyright (C) 2023 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 android.hardware.camera2.extension; 18 19 import android.annotation.FlaggedApi; 20 import android.annotation.NonNull; 21 import android.annotation.SystemApi; 22 import android.hardware.camera2.CameraAccessException; 23 import android.hardware.camera2.CameraCharacteristics; 24 import android.hardware.camera2.CameraManager; 25 import android.hardware.camera2.CaptureRequest; 26 import android.hardware.camera2.CaptureResult; 27 import android.hardware.camera2.impl.CameraMetadataNative; 28 import android.hardware.camera2.impl.CaptureCallback; 29 import android.util.Log; 30 import android.util.Pair; 31 import android.util.Size; 32 33 import com.android.internal.camera.flags.Flags; 34 35 import java.util.ArrayList; 36 import java.util.HashMap; 37 import java.util.List; 38 import java.util.Map; 39 40 /** 41 * Advanced contract for implementing Extensions. ImageCapture/Preview 42 * Extensions are both implemented on this interface. 43 * 44 * <p>This advanced contract empowers implementations to gain access to 45 * more Camera2 capability. This includes: (1) Add custom surfaces with 46 * specific formats like {@link android.graphics.ImageFormat#YUV_420_888}, 47 * {@link android.graphics.ImageFormat#RAW10}, {@link android.graphics.ImageFormat#RAW_DEPTH10}. 48 * (2) Access to the capture request callbacks as well as all the images retrieved of 49 * various image formats. (3) 50 * Able to triggers single or repeating request with the capabilities to 51 * specify target surfaces, template id and parameters. 52 * 53 * @hide 54 */ 55 @SystemApi 56 @FlaggedApi(Flags.FLAG_CONCERT_MODE) 57 public abstract class AdvancedExtender { 58 private HashMap<String, Long> mMetadataVendorIdMap = new HashMap<>(); 59 private final CameraManager mCameraManager; 60 61 private CameraUsageTracker mCameraUsageTracker; 62 private static final String TAG = "AdvancedExtender"; 63 64 /** 65 * Initialize a camera extension advanced extender instance. 66 * 67 * @param cameraManager the system camera manager 68 */ 69 @FlaggedApi(Flags.FLAG_CONCERT_MODE) AdvancedExtender(@onNull CameraManager cameraManager)70 public AdvancedExtender(@NonNull CameraManager cameraManager) { 71 mCameraManager = cameraManager; 72 try { 73 String [] cameraIds = mCameraManager.getCameraIdListNoLazy(); 74 if (cameraIds != null) { 75 for (String cameraId : cameraIds) { 76 CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId); 77 Object thisClass = CameraCharacteristics.Key.class; 78 Class<CameraCharacteristics.Key<?>> keyClass = 79 (Class<CameraCharacteristics.Key<?>>)thisClass; 80 ArrayList<CameraCharacteristics.Key<?>> vendorKeys = 81 chars.getNativeMetadata().getAllVendorKeys(keyClass); 82 if ((vendorKeys != null) && !vendorKeys.isEmpty()) { 83 mMetadataVendorIdMap.put(cameraId, vendorKeys.get(0).getVendorId()); 84 } 85 } 86 } 87 } catch (CameraAccessException e) { 88 Log.e(TAG, "Failed to query camera characteristics!"); 89 } 90 } 91 setCameraUsageTracker(CameraUsageTracker tracker)92 void setCameraUsageTracker(CameraUsageTracker tracker) { 93 mCameraUsageTracker = tracker; 94 } 95 96 /** 97 * Returns the camera metadata vendor id, that can be used to 98 * configure and enable vendor tag support for a particular 99 * camera metadata buffer. 100 * 101 * @param cameraId The camera2 id string of the camera. 102 * @return the camera metadata vendor Id associated with the given camera 103 */ 104 @FlaggedApi(Flags.FLAG_CONCERT_MODE) getMetadataVendorId(@onNull String cameraId)105 public long getMetadataVendorId(@NonNull String cameraId) { 106 long vendorId = mMetadataVendorIdMap.containsKey(cameraId) ? 107 mMetadataVendorIdMap.get(cameraId) : Long.MAX_VALUE; 108 return vendorId; 109 } 110 111 /** 112 * Indicates whether the extension is supported on the device. 113 * 114 * @param cameraId The camera2 id string of the camera. 115 * @param charsMap A map consisting of the camera ids and 116 * the {@link android.hardware.camera2.CameraCharacteristics}s. For 117 * every camera, the map contains at least 118 * the CameraCharacteristics for the camera 119 * id. 120 * If the camera is logical camera, it will 121 * also contain associated 122 * physical camera ids and their 123 * CameraCharacteristics. 124 * @return true if the extension is supported, otherwise false 125 */ 126 @FlaggedApi(Flags.FLAG_CONCERT_MODE) isExtensionAvailable(@onNull String cameraId, @NonNull CharacteristicsMap charsMap)127 public abstract boolean isExtensionAvailable(@NonNull String cameraId, 128 @NonNull CharacteristicsMap charsMap); 129 130 /** 131 * Initializes the extender to be used with the specified camera. 132 * 133 * <p>This should be called before any other method on the extender. 134 * The exception is {@link #isExtensionAvailable}. 135 * 136 * @param cameraId The camera2 id string of the camera. 137 * @param map A map consisting of the camera ids and 138 * the {@link android.hardware.camera2.CameraCharacteristics}s. For 139 * every camera, the map contains at least 140 * the CameraCharacteristics for the camera 141 * id. 142 * If the camera is logical camera, it will 143 * also contain associated 144 * physical camera ids and their 145 * CameraCharacteristics. 146 */ 147 @FlaggedApi(Flags.FLAG_CONCERT_MODE) initialize(@onNull String cameraId, @NonNull CharacteristicsMap map)148 public abstract void initialize(@NonNull String cameraId, @NonNull CharacteristicsMap map); 149 150 /** 151 * Returns supported output format/size map for preview. The format 152 * could be {@link android.graphics.ImageFormat#PRIVATE} or 153 * {@link android.graphics.ImageFormat#YUV_420_888}. Implementations must support 154 * {@link android.graphics.ImageFormat#PRIVATE} format at least. 155 * An example of how the map is parsed can be found in 156 * {@link #initializeParcelable(Map)} 157 * 158 * <p>The preview surface format in the CameraCaptureSession may not 159 * be identical to the supported preview output format returned here. 160 * @param cameraId The camera2 id string of the camera. 161 */ 162 @FlaggedApi(Flags.FLAG_CONCERT_MODE) 163 @NonNull getSupportedPreviewOutputResolutions( @onNull String cameraId)164 public abstract Map<Integer, List<Size>> getSupportedPreviewOutputResolutions( 165 @NonNull String cameraId); 166 167 /** 168 * Returns supported output format/size map for image capture. OEM is 169 * required to support both {@link android.graphics.ImageFormat#JPEG} and 170 * {@link android.graphics.ImageFormat#YUV_420_888} format output. 171 * An example of how the map is parsed can be found in 172 * {@link #initializeParcelable(Map)} 173 * 174 * <p>The surface created with this supported 175 * format/size could be either added in CameraCaptureSession with HAL 176 * processing OR it configures intermediate surfaces( 177 * {@link android.graphics.ImageFormat#YUV_420_888}/ 178 * {@link android.graphics.ImageFormat#RAW10}..) and 179 * writes the output to the output surface. 180 * @param cameraId The camera2 id string of the camera. 181 */ 182 @FlaggedApi(Flags.FLAG_CONCERT_MODE) 183 @NonNull getSupportedCaptureOutputResolutions( @onNull String cameraId)184 public abstract Map<Integer, List<Size>> getSupportedCaptureOutputResolutions( 185 @NonNull String cameraId); 186 187 /** 188 * Returns a processor for activating extension sessions. It 189 * implements all the interactions required for starting an extension 190 * and cleanup. 191 */ 192 @FlaggedApi(Flags.FLAG_CONCERT_MODE) 193 @NonNull getSessionProcessor()194 public abstract SessionProcessor getSessionProcessor(); 195 196 /** 197 * Returns a list of orthogonal capture request keys. 198 * 199 * <p>Any keys included in the list will be configurable by clients of 200 * the extension and will affect the extension functionality.</p> 201 * 202 * <p>Please note that the keys {@link CaptureRequest#JPEG_QUALITY} 203 * and {@link CaptureRequest#JPEG_ORIENTATION} are always supported 204 * regardless of being added to the list or not. To support common 205 * camera operations like zoom, tap-to-focus, flash and 206 * exposure compensation, we recommend supporting the following keys 207 * if possible. 208 * <pre> 209 * zoom: {@link CaptureRequest#CONTROL_ZOOM_RATIO} 210 * {@link CaptureRequest#SCALER_CROP_REGION} 211 * tap-to-focus: 212 * {@link CaptureRequest#CONTROL_AF_MODE} 213 * {@link CaptureRequest#CONTROL_AF_TRIGGER} 214 * {@link CaptureRequest#CONTROL_AF_REGIONS} 215 * {@link CaptureRequest#CONTROL_AE_REGIONS} 216 * {@link CaptureRequest#CONTROL_AWB_REGIONS} 217 * flash: 218 * {@link CaptureRequest#CONTROL_AE_MODE} 219 * {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER} 220 * {@link CaptureRequest#FLASH_MODE} 221 * exposure compensation: 222 * {@link CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION} 223 * </pre> 224 * 225 * @param cameraId The camera2 id string of the camera. 226 * 227 * @return The list of supported orthogonal capture keys, or empty 228 * list if no capture settings are not supported. 229 */ 230 @FlaggedApi(Flags.FLAG_CONCERT_MODE) 231 @NonNull getAvailableCaptureRequestKeys( @onNull String cameraId)232 public abstract List<CaptureRequest.Key> getAvailableCaptureRequestKeys( 233 @NonNull String cameraId); 234 235 /** 236 * Returns a list of supported capture result keys. 237 * 238 * <p>Any keys included in this list must be available as part of the 239 * registered {@link CaptureCallback#onCaptureCompleted} callback.</p> 240 * 241 * <p>At the very minimum, it is expected that the result key list is 242 * a superset of the capture request keys.</p> 243 * 244 * @param cameraId The camera2 id string of the camera. 245 * @return The list of supported capture result keys, or 246 * empty list if capture results are not supported. 247 */ 248 @FlaggedApi(Flags.FLAG_CONCERT_MODE) 249 @NonNull getAvailableCaptureResultKeys( @onNull String cameraId)250 public abstract List<CaptureResult.Key> getAvailableCaptureResultKeys( 251 @NonNull String cameraId); 252 253 /** 254 * Returns a list of {@link CameraCharacteristics} key/value pairs for apps to use when 255 * querying the Extensions specific {@link CameraCharacteristics}. 256 * 257 * <p>To ensure the correct {@link CameraCharacteristics} are used when an extension is 258 * enabled, an application should prioritize the value returned from the list if the 259 * {@link CameraCharacteristics} key is present. If the key doesn't exist in the returned list, 260 * then the application should query the value using 261 * {@link CameraCharacteristics#get(CameraCharacteristics.Key)}. 262 * 263 * <p>For example, an extension may limit the zoom ratio range. In this case, an OEM can return 264 * a new zoom ratio range for the key {@link CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE}. 265 * 266 * <p> Currently, the only synthetic keys supported for override are 267 * {@link CameraCharacteristics#REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES} and 268 * {@link CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES}. To enable them, an OEM 269 * should override the respective native keys 270 * {@link CameraCharacteristics#REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP} and 271 * {@link CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP}. 272 */ 273 @FlaggedApi(Flags.FLAG_CAMERA_EXTENSIONS_CHARACTERISTICS_GET) 274 @NonNull 275 public abstract List<Pair<CameraCharacteristics.Key, Object>> getAvailableCharacteristicsKeyValues()276 getAvailableCharacteristicsKeyValues(); 277 278 private final class AdvancedExtenderImpl extends IAdvancedExtenderImpl.Stub { 279 @Override isExtensionAvailable(String cameraId, Map<String, CameraMetadataNative> charsMapNative)280 public boolean isExtensionAvailable(String cameraId, 281 Map<String, CameraMetadataNative> charsMapNative) { 282 return AdvancedExtender.this.isExtensionAvailable(cameraId, 283 new CharacteristicsMap(charsMapNative)); 284 } 285 286 @Override init(String cameraId, Map<String, CameraMetadataNative> charsMapNative)287 public void init(String cameraId, Map<String, CameraMetadataNative> charsMapNative) { 288 AdvancedExtender.this.initialize(cameraId, new CharacteristicsMap(charsMapNative)); 289 } 290 291 @Override getSupportedPostviewResolutions( android.hardware.camera2.extension.Size captureSize)292 public List<SizeList> getSupportedPostviewResolutions( 293 android.hardware.camera2.extension.Size captureSize) { 294 // Feature is currently unsupported 295 return null; 296 } 297 298 @Override getSupportedPreviewOutputResolutions(String cameraId)299 public List<SizeList> getSupportedPreviewOutputResolutions(String cameraId) { 300 return initializeParcelable( 301 AdvancedExtender.this.getSupportedPreviewOutputResolutions(cameraId)); 302 } 303 304 @Override getSupportedCaptureOutputResolutions(String cameraId)305 public List<SizeList> getSupportedCaptureOutputResolutions(String cameraId) { 306 return initializeParcelable( 307 AdvancedExtender.this.getSupportedCaptureOutputResolutions(cameraId)); 308 } 309 310 @Override getEstimatedCaptureLatencyRange(String cameraId, android.hardware.camera2.extension.Size outputSize, int format)311 public LatencyRange getEstimatedCaptureLatencyRange(String cameraId, 312 android.hardware.camera2.extension.Size outputSize, int format) { 313 // Feature is currently unsupported 314 return null; 315 } 316 317 @Override getSessionProcessor()318 public ISessionProcessorImpl getSessionProcessor() { 319 SessionProcessor processor =AdvancedExtender.this.getSessionProcessor(); 320 processor.setCameraUsageTracker(mCameraUsageTracker); 321 return processor.getSessionProcessorBinder(); 322 } 323 324 @Override getAvailableCaptureRequestKeys(String cameraId)325 public CameraMetadataNative getAvailableCaptureRequestKeys(String cameraId) { 326 List<CaptureRequest.Key> supportedCaptureKeys = 327 AdvancedExtender.this.getAvailableCaptureRequestKeys(cameraId); 328 329 if (!supportedCaptureKeys.isEmpty()) { 330 CameraMetadataNative ret = new CameraMetadataNative(); 331 long vendorId = getMetadataVendorId(cameraId); 332 ret.setVendorId(vendorId); 333 int requestKeyTags[] = new int[supportedCaptureKeys.size()]; 334 int i = 0; 335 for (CaptureRequest.Key key : supportedCaptureKeys) { 336 requestKeyTags[i++] = CameraMetadataNative.getTag(key.getName(), vendorId); 337 } 338 ret.set(CameraCharacteristics.REQUEST_AVAILABLE_REQUEST_KEYS, requestKeyTags); 339 340 return ret; 341 } 342 343 return null; 344 } 345 346 @Override getAvailableCaptureResultKeys(String cameraId)347 public CameraMetadataNative getAvailableCaptureResultKeys(String cameraId) { 348 List<CaptureResult.Key> supportedResultKeys = 349 AdvancedExtender.this.getAvailableCaptureResultKeys(cameraId); 350 351 if (!supportedResultKeys.isEmpty()) { 352 CameraMetadataNative ret = new CameraMetadataNative(); 353 long vendorId = getMetadataVendorId(cameraId); 354 ret.setVendorId(vendorId); 355 int resultKeyTags [] = new int[supportedResultKeys.size()]; 356 int i = 0; 357 for (CaptureResult.Key key : supportedResultKeys) { 358 resultKeyTags[i++] = CameraMetadataNative.getTag(key.getName(), vendorId); 359 } 360 ret.set(CameraCharacteristics.REQUEST_AVAILABLE_RESULT_KEYS, resultKeyTags); 361 362 return ret; 363 } 364 365 return null; 366 } 367 368 @Override isCaptureProcessProgressAvailable()369 public boolean isCaptureProcessProgressAvailable() { 370 // Feature is currently unsupported 371 return false; 372 } 373 374 @Override isPostviewAvailable()375 public boolean isPostviewAvailable() { 376 // Feature is currently unsupported 377 return false; 378 } 379 380 @FlaggedApi(Flags.FLAG_CAMERA_EXTENSIONS_CHARACTERISTICS_GET) 381 @Override getAvailableCharacteristicsKeyValues(String cameraId)382 public CameraMetadataNative getAvailableCharacteristicsKeyValues(String cameraId) { 383 List<Pair<CameraCharacteristics.Key, Object>> entries = 384 AdvancedExtender.this.getAvailableCharacteristicsKeyValues(); 385 386 if ((entries != null) && !entries.isEmpty()) { 387 CameraMetadataNative ret = new CameraMetadataNative(); 388 long vendorId = mMetadataVendorIdMap.containsKey(cameraId) 389 ? mMetadataVendorIdMap.get(cameraId) : Long.MAX_VALUE; 390 ret.setVendorId(vendorId); 391 int[] characteristicsKeyTags = new int[entries.size()]; 392 int i = 0; 393 for (Pair<CameraCharacteristics.Key, Object> entry : entries) { 394 int tag = CameraMetadataNative.getTag(entry.first.getName(), vendorId); 395 characteristicsKeyTags[i++] = tag; 396 ret.set(entry.first, entry.second); 397 } 398 ret.set(CameraCharacteristics.REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, 399 characteristicsKeyTags); 400 401 return ret; 402 } 403 404 return null; 405 } 406 } 407 getAdvancedExtenderBinder()408 @NonNull IAdvancedExtenderImpl getAdvancedExtenderBinder() { 409 return new AdvancedExtenderImpl(); 410 } 411 initializeParcelable( Map<Integer, List<android.util.Size>> sizes)412 private static List<SizeList> initializeParcelable( 413 Map<Integer, List<android.util.Size>> sizes) { 414 if (sizes == null) { 415 return null; 416 } 417 ArrayList<SizeList> ret = new ArrayList<>(sizes.size()); 418 for (Map.Entry<Integer, List<android.util.Size>> entry : sizes.entrySet()) { 419 SizeList sizeList = new SizeList(); 420 sizeList.format = entry.getKey(); 421 sizeList.sizes = new ArrayList<>(); 422 for (android.util.Size size : entry.getValue()) { 423 android.hardware.camera2.extension.Size sz = 424 new android.hardware.camera2.extension.Size(); 425 sz.width = size.getWidth(); 426 sz.height = size.getHeight(); 427 sizeList.sizes.add(sz); 428 } 429 ret.add(sizeList); 430 } 431 432 return ret; 433 } 434 } 435