1 /* 2 * Copyright 2020 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.core; 18 19 import static androidx.camera.core.impl.SessionConfig.DEFAULT_SESSION_TYPE; 20 21 import android.annotation.SuppressLint; 22 import android.graphics.Matrix; 23 import android.graphics.Rect; 24 import android.graphics.SurfaceTexture; 25 import android.hardware.camera2.CameraCharacteristics; 26 import android.util.Range; 27 import android.util.Size; 28 import android.view.Display; 29 import android.view.Surface; 30 import android.view.SurfaceView; 31 import android.view.TextureView; 32 33 import androidx.annotation.GuardedBy; 34 import androidx.annotation.IntDef; 35 import androidx.annotation.RestrictTo; 36 import androidx.camera.core.impl.CameraInternal; 37 import androidx.camera.core.impl.DeferrableSurface; 38 import androidx.camera.core.impl.ImageFormatConstants; 39 import androidx.camera.core.impl.ImageOutputConfig; 40 import androidx.camera.core.impl.StreamSpec; 41 import androidx.camera.core.impl.utils.executor.CameraXExecutors; 42 import androidx.camera.core.impl.utils.futures.FutureCallback; 43 import androidx.camera.core.impl.utils.futures.Futures; 44 import androidx.concurrent.futures.CallbackToFutureAdapter; 45 import androidx.core.util.Consumer; 46 import androidx.core.util.Preconditions; 47 48 import com.google.auto.value.AutoValue; 49 import com.google.common.util.concurrent.ListenableFuture; 50 51 import org.jspecify.annotations.NonNull; 52 import org.jspecify.annotations.Nullable; 53 54 import java.lang.annotation.Retention; 55 import java.lang.annotation.RetentionPolicy; 56 import java.util.concurrent.CancellationException; 57 import java.util.concurrent.ExecutionException; 58 import java.util.concurrent.Executor; 59 import java.util.concurrent.atomic.AtomicReference; 60 61 /** 62 * A completable, single-use request of a {@link Surface}. 63 * 64 * <p>Contains requirements for surface characteristics along with methods for completing the 65 * request and listening for request cancellation. 66 * 67 * <p>Acts as a bridge between the surface provider and the surface requester. The diagram below 68 * describes how it works: 69 * <ol> 70 * <li>The surface provider gives a reference to surface requester for providing {@link Surface} 71 * (e.g. {@link Preview#setSurfaceProvider(Preview.SurfaceProvider)}). 72 * <li>The surface requester uses the reference to send a {@code SurfaceRequest} to get a 73 * {@link Surface} (e.g. {@link Preview.SurfaceProvider#onSurfaceRequested(SurfaceRequest)}). 74 * <li>The surface provider can use {@link #provideSurface(Surface, Executor, Consumer)} to provide 75 * a {@link Surface} or inform the surface requester no {@link Surface} will be provided with 76 * {@link #willNotProvideSurface()}. If a {@link Surface} is provided, the connection between 77 * surface provider and surface requester is established. 78 * <li>If the connection is established, the surface requester can get the {@link Surface} through 79 * {@link #getDeferrableSurface()} and start to send frame data. 80 * <li>If for some reason the provided {@link Surface} is no longer valid (e.g. when the 81 * SurfaceView destroys its surface due to page being slid out in ViewPager2), the surface 82 * provider can use {@link #invalidate()} method to inform the surface requester and the 83 * established connection will be closed. 84 * <li>The surface requester will re-send a new {@code SurfaceRequest} to establish a new 85 * connection. 86 * </ol> 87 * 88 * <img src="/images/reference/androidx/camera/camera-core/surface_request_work_flow.svg"/> 89 */ 90 public final class SurfaceRequest { 91 92 /** 93 * A frame rate range with no specified lower or upper bound. 94 * 95 * @see SurfaceRequest#getExpectedFrameRate() 96 */ 97 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 98 public static final Range<Integer> FRAME_RATE_RANGE_UNSPECIFIED = 99 StreamSpec.FRAME_RATE_RANGE_UNSPECIFIED; 100 101 private final Object mLock = new Object(); 102 103 private final Size mResolution; 104 105 private final @NonNull DynamicRange mDynamicRange; 106 107 private final Range<Integer> mExpectedFrameRate; 108 private final CameraInternal mCamera; 109 private final boolean mIsPrimary; 110 private final int mSessionType; 111 112 // For the camera to retrieve the surface from the user 113 @SuppressWarnings("WeakerAccess") /*synthetic accessor */ 114 final ListenableFuture<Surface> mSurfaceFuture; 115 private final CallbackToFutureAdapter.Completer<Surface> mSurfaceCompleter; 116 117 // For the user to wait for the camera to be finished with the surface and retrieve errors 118 // from the camera. 119 private final ListenableFuture<Void> mSessionStatusFuture; 120 121 // For notification of surface recreated. 122 private final CallbackToFutureAdapter.@NonNull Completer<Void> mSurfaceRecreationCompleter; 123 124 // For notification of surface request cancellation. Should only be used to register 125 // cancellation listeners. 126 private final CallbackToFutureAdapter.Completer<Void> mRequestCancellationCompleter; 127 128 private final DeferrableSurface mInternalDeferrableSurface; 129 130 @GuardedBy("mLock") 131 private @Nullable TransformationInfo mTransformationInfo; 132 @GuardedBy("mLock") 133 private @Nullable TransformationInfoListener mTransformationInfoListener; 134 // Executor for calling TransformationUpdateListener. 135 @GuardedBy("mLock") 136 private @Nullable Executor mTransformationInfoExecutor; 137 138 /** 139 * Creates a new surface request with the given resolution and {@link Camera}. 140 */ 141 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) SurfaceRequest( @onNull Size resolution, @NonNull CameraInternal camera, @NonNull Runnable onInvalidated)142 public SurfaceRequest( 143 @NonNull Size resolution, 144 @NonNull CameraInternal camera, 145 @NonNull Runnable onInvalidated) { 146 this(resolution, camera, DynamicRange.SDR, FRAME_RATE_RANGE_UNSPECIFIED, onInvalidated); 147 } 148 149 /** 150 * Creates a new surface request with the given resolution, {@link Camera}, dynamic range, and 151 * expected frame rate. 152 */ 153 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) SurfaceRequest( @onNull Size resolution, @NonNull CameraInternal camera, @NonNull DynamicRange dynamicRange, @NonNull Range<Integer> expectedFrameRate, @NonNull Runnable onInvalidated)154 public SurfaceRequest( 155 @NonNull Size resolution, 156 @NonNull CameraInternal camera, 157 @NonNull DynamicRange dynamicRange, 158 @NonNull Range<Integer> expectedFrameRate, 159 @NonNull Runnable onInvalidated) { 160 this(resolution, camera, true, dynamicRange, DEFAULT_SESSION_TYPE, 161 expectedFrameRate, onInvalidated); 162 } 163 164 /** 165 * Creates a new surface request with the given resolution, {@link Camera}, dynamic range, and 166 * expected frame rate and whether it's primary or secondary camera. 167 */ 168 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) SurfaceRequest( @onNull Size resolution, @NonNull CameraInternal camera, boolean isPrimary, @NonNull DynamicRange dynamicRange, int sessionType, @NonNull Range<Integer> expectedFrameRate, @NonNull Runnable onInvalidated)169 public SurfaceRequest( 170 @NonNull Size resolution, 171 @NonNull CameraInternal camera, 172 boolean isPrimary, 173 @NonNull DynamicRange dynamicRange, 174 int sessionType, 175 @NonNull Range<Integer> expectedFrameRate, 176 @NonNull Runnable onInvalidated) { 177 super(); 178 mResolution = resolution; 179 mCamera = camera; 180 mIsPrimary = isPrimary; 181 Preconditions.checkArgument(dynamicRange.isFullySpecified(), 182 "SurfaceRequest's DynamicRange must always be fully specified."); 183 mDynamicRange = dynamicRange; 184 mSessionType = sessionType; 185 mExpectedFrameRate = expectedFrameRate; 186 187 // To ensure concurrency and ordering, operations are chained. Completion can only be 188 // triggered externally by the top-level completer (mSurfaceCompleter). The other future 189 // completers are only completed by callbacks set up within the constructor of this class 190 // to ensure correct ordering of events. 191 192 // Cancellation listener must be called last to ensure the result can be retrieved from 193 // the session listener. 194 String surfaceRequestString = 195 "SurfaceRequest[size: " + resolution + ", id: " + this.hashCode() + "]"; 196 AtomicReference<CallbackToFutureAdapter.Completer<Void>> cancellationCompleterRef = 197 new AtomicReference<>(null); 198 ListenableFuture<Void> requestCancellationFuture = 199 CallbackToFutureAdapter.getFuture(completer -> { 200 cancellationCompleterRef.set(completer); 201 return surfaceRequestString + "-cancellation"; 202 }); 203 CallbackToFutureAdapter.Completer<Void> requestCancellationCompleter = 204 Preconditions.checkNotNull(cancellationCompleterRef.get()); 205 mRequestCancellationCompleter = requestCancellationCompleter; 206 207 // Surface session status future completes and is responsible for finishing the 208 // cancellation listener. 209 AtomicReference<CallbackToFutureAdapter.Completer<Void>> sessionStatusCompleterRef = 210 new AtomicReference<>(null); 211 mSessionStatusFuture = CallbackToFutureAdapter.getFuture(completer -> { 212 sessionStatusCompleterRef.set(completer); 213 return surfaceRequestString + "-status"; 214 }); 215 216 Futures.addCallback(mSessionStatusFuture, new FutureCallback<Void>() { 217 @Override 218 public void onSuccess(@Nullable Void result) { 219 // Cancellation didn't occur, so complete the cancellation future. There 220 // shouldn't ever be any standard listeners on this future, so nothing should be 221 // invoked. 222 Preconditions.checkState(requestCancellationCompleter.set(null)); 223 } 224 225 @Override 226 public void onFailure(@NonNull Throwable t) { 227 if (t instanceof RequestCancelledException) { 228 // Cancellation occurred. Notify listeners. 229 Preconditions.checkState(requestCancellationFuture.cancel(false)); 230 } else { 231 // Cancellation didn't occur, complete the future so cancellation listeners 232 // are not invoked. 233 Preconditions.checkState(requestCancellationCompleter.set(null)); 234 } 235 } 236 }, CameraXExecutors.directExecutor()); 237 238 // Create the surface future/completer. This will be used to complete the rest of the 239 // future chain and can be set externally via SurfaceRequest methods. 240 CallbackToFutureAdapter.Completer<Void> sessionStatusCompleter = 241 Preconditions.checkNotNull(sessionStatusCompleterRef.get()); 242 AtomicReference<CallbackToFutureAdapter.Completer<Surface>> surfaceCompleterRef = 243 new AtomicReference<>(null); 244 mSurfaceFuture = CallbackToFutureAdapter.getFuture(completer -> { 245 surfaceCompleterRef.set(completer); 246 return surfaceRequestString + "-Surface"; 247 }); 248 mSurfaceCompleter = Preconditions.checkNotNull(surfaceCompleterRef.get()); 249 250 // Create the deferrable surface which will be used for communicating when the 251 // camera and consumer are done using the surface. Note this anonymous inner class holds 252 // an implicit reference to the SurfaceRequest. This is by design, and ensures the 253 // SurfaceRequest and all contained future completers will not be garbage collected as 254 // long as the DeferrableSurface is referenced externally (via getDeferrableSurface()). 255 mInternalDeferrableSurface = new DeferrableSurface(resolution, 256 ImageFormatConstants.INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE) { 257 @Override 258 protected @NonNull ListenableFuture<Surface> provideSurface() { 259 return mSurfaceFuture; 260 } 261 }; 262 ListenableFuture<Void> terminationFuture = 263 mInternalDeferrableSurface.getTerminationFuture(); 264 265 // Propagate surface completion to the session future. 266 Futures.addCallback(mSurfaceFuture, new FutureCallback<Surface>() { 267 @Override 268 public void onSuccess(@Nullable Surface result) { 269 // On successful setting of a surface, defer completion of the session future to 270 // the DeferrableSurface termination future. Once that future completes, then it 271 // is safe to release the Surface and associated resources. 272 Futures.propagate(terminationFuture, sessionStatusCompleter); 273 } 274 275 @Override 276 public void onFailure(@NonNull Throwable t) { 277 // Translate cancellation into a SurfaceRequestCancelledException. Other 278 // exceptions mean either the request was completed via willNotProvideSurface() or a 279 // programming error occurred. In either case, the user will never see the 280 // session future (an immediate future will be returned instead), so complete the 281 // future so cancellation listeners are never called. 282 if (t instanceof CancellationException) { 283 Preconditions.checkState(sessionStatusCompleter.setException( 284 new RequestCancelledException( 285 surfaceRequestString + " cancelled.", t))); 286 } else { 287 sessionStatusCompleter.set(null); 288 } 289 } 290 }, CameraXExecutors.directExecutor()); 291 292 // If the deferrable surface is terminated, there are two cases: 293 // 1. The surface has not yet been provided to the camera (or marked as 'will not 294 // complete'). Treat this as if the surface request has been cancelled. 295 // 2. The surface was already provided to the camera. In this case the camera is now 296 // finished with the surface, so cancelling the surface future below will be a no-op. 297 terminationFuture.addListener(() -> mSurfaceFuture.cancel(true), 298 CameraXExecutors.directExecutor()); 299 300 mSurfaceRecreationCompleter = initialSurfaceRecreationCompleter( 301 CameraXExecutors.directExecutor(), onInvalidated); 302 } 303 304 /** 305 * Returns the {@link DeferrableSurface} instance used to track usage of the surface that 306 * fulfills this request. 307 */ 308 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) getDeferrableSurface()309 public @NonNull DeferrableSurface getDeferrableSurface() { 310 return mInternalDeferrableSurface; 311 } 312 313 /** 314 * Returns whether this surface request has been serviced. 315 * 316 * <p>A surface request is considered serviced if 317 * {@link #provideSurface(Surface, Executor, Consumer)} or {@link #willNotProvideSurface()} 318 * has been called. 319 */ 320 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) isServiced()321 public boolean isServiced() { 322 return mSurfaceFuture.isDone(); 323 } 324 325 /** 326 * Returns the resolution of the requested {@link Surface}. 327 * 328 * <p>The surface which fulfills this request must have the resolution specified here in 329 * order to fulfill the resource requirements of the camera. Fulfillment of the request 330 * with a surface of a different resolution may cause the {@code resultListener} passed to 331 * {@link #provideSurface(Surface, Executor, Consumer)} to be invoked with a {@link Result} 332 * containing {@link Result#RESULT_INVALID_SURFACE}. 333 * 334 * @return The guaranteed supported resolution. 335 * @see SurfaceTexture#setDefaultBufferSize(int, int) 336 */ getResolution()337 public @NonNull Size getResolution() { 338 return mResolution; 339 } 340 341 /** 342 * Returns the dynamic range expected to be used with the requested surface. 343 * 344 * <p>The dynamic range may have implications for which surface type is returned. Special 345 * care should be taken to ensure the provided surface can support the requested dynamic 346 * range. For example, if the returned dynamic range has {@link DynamicRange#getBitDepth()} 347 * equal to {@link DynamicRange#BIT_DEPTH_10_BIT}, then the surface provided to 348 * {@link #provideSurface(Surface, Executor, Consumer)} should use an 349 * {@link android.graphics.ImageFormat} that can support ten bits of dynamic range, such as 350 * {@link android.graphics.ImageFormat#PRIVATE} or 351 * {@link android.graphics.ImageFormat#YCBCR_P010}. 352 * 353 * <p>The dynamic range returned here will always be fully specified. That is, it will never 354 * have an {@link DynamicRange#getEncoding() encoding} of 355 * {@link DynamicRange#ENCODING_UNSPECIFIED} or {@link DynamicRange#ENCODING_HDR_UNSPECIFIED} 356 * and will never have {@link DynamicRange#getBitDepth() bit depth} of 357 * {@link DynamicRange#BIT_DEPTH_UNSPECIFIED}. 358 */ getDynamicRange()359 public @NonNull DynamicRange getDynamicRange() { 360 return mDynamicRange; 361 } 362 363 /** Returns the session type associated with the surface request. */ 364 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) getSessionType()365 public int getSessionType() { 366 return mSessionType; 367 } 368 369 /** 370 * Returns the expected rate at which frames will be produced into the provided {@link Surface}. 371 * 372 * <p>This information can be used to configure components that can be optimized by knowing 373 * the frame rate. For example, {@link android.media.MediaCodec} can be configured with the 374 * correct bitrate calculated from the frame rate. 375 * 376 * <p>The range may represent a variable frame rate, in which case {@link Range#getUpper()} 377 * and {@link Range#getLower()} will be different values. This is commonly used by 378 * auto-exposure algorithms to ensure a scene is exposed correctly in varying lighting 379 * conditions. The frame rate may also be fixed, in which case {@link Range#getUpper()} will 380 * be equivalent to {@link Range#getLower()}. 381 * 382 * <p>This method may also return {@link #FRAME_RATE_RANGE_UNSPECIFIED} if no information about 383 * the frame rate can be determined. In this case, no assumptions should be made about what 384 * the actual frame rate will be. 385 * 386 * @return The expected frame rate range or {@link #FRAME_RATE_RANGE_UNSPECIFIED} if no frame 387 * rate information is available. 388 */ 389 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) getExpectedFrameRate()390 public @NonNull Range<Integer> getExpectedFrameRate() { 391 return mExpectedFrameRate; 392 } 393 394 /** 395 * Returns the {@link Camera} which is requesting a {@link Surface}. 396 */ 397 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) getCamera()398 public @NonNull CameraInternal getCamera() { 399 return mCamera; 400 } 401 402 /** 403 * Returns whether the {@link Camera} is primary or secondary in dual camera case. 404 * The value is always true for single camera case. 405 */ 406 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) isPrimary()407 public boolean isPrimary() { 408 return mIsPrimary; 409 } 410 411 /** 412 * Completes the request for a {@link Surface} if it has not already been 413 * completed or cancelled. 414 * 415 * <p>Once the camera no longer needs the provided surface, the {@code resultListener} will be 416 * invoked with a {@link Result} containing {@link Result#RESULT_SURFACE_USED_SUCCESSFULLY}. 417 * At this point it is safe to release the surface and any underlying resources. Releasing 418 * the surface before receiving this signal may cause undesired behavior on lower API levels. 419 * 420 * <p>If the request is cancelled by the camera before successfully attaching the 421 * provided surface to the camera, then the {@code resultListener} will be invoked with a 422 * {@link Result} containing {@link Result#RESULT_REQUEST_CANCELLED}. In addition, any 423 * cancellation listeners provided to 424 * {@link #addRequestCancellationListener(Executor, Runnable)} will be invoked. 425 * 426 * <p>If the request was previously completed via {@link #willNotProvideSurface()}, then 427 * {@code resultListener} will be invoked with a {@link Result} containing 428 * {@link Result#RESULT_WILL_NOT_PROVIDE_SURFACE}. 429 * 430 * <p>Upon returning from this method, the surface request is guaranteed to be complete. 431 * However, only the {@code resultListener} provided to the first invocation of this method 432 * should be used to track when the provided {@link Surface} is no longer in use by the 433 * camera, as subsequent invocations will always invoke the {@code resultListener} with a 434 * {@link Result} containing {@link Result#RESULT_SURFACE_ALREADY_PROVIDED}. 435 * 436 * @param surface The surface which will complete the request. 437 * @param executor Executor used to execute the {@code resultListener}. 438 * @param resultListener Listener used to track how the surface is used by the camera in 439 * response to being provided by this method. 440 */ provideSurface(@onNull Surface surface, @NonNull Executor executor, @NonNull Consumer<Result> resultListener)441 public void provideSurface(@NonNull Surface surface, @NonNull Executor executor, 442 @NonNull Consumer<Result> resultListener) { 443 if (!surface.isValid()) { 444 // Only check Surface validness. The resolution match check might cause unexpected 445 // compatibility issue. 446 executor.execute( 447 () -> resultListener.accept( 448 Result.of(Result.RESULT_INVALID_SURFACE, surface))); 449 return; 450 } 451 452 if (mSurfaceCompleter.set(surface) || mSurfaceFuture.isCancelled()) { 453 // Session will be pending completion (or surface request was cancelled). Return the 454 // session future. 455 Futures.addCallback(mSessionStatusFuture, new FutureCallback<Void>() { 456 @Override 457 public void onSuccess(@Nullable Void result) { 458 resultListener.accept(Result.of(Result.RESULT_SURFACE_USED_SUCCESSFULLY, 459 surface)); 460 } 461 462 @Override 463 public void onFailure(@NonNull Throwable t) { 464 Preconditions.checkState(t instanceof RequestCancelledException, "Camera " 465 + "surface session should only fail with request " 466 + "cancellation. Instead failed due to:\n" + t); 467 resultListener.accept(Result.of(Result.RESULT_REQUEST_CANCELLED, surface)); 468 } 469 }, executor); 470 } else { 471 // Surface request is already complete 472 Preconditions.checkState(mSurfaceFuture.isDone()); 473 try { 474 mSurfaceFuture.get(); 475 // Getting this far means the surface was already provided. 476 executor.execute( 477 () -> resultListener.accept( 478 Result.of(Result.RESULT_SURFACE_ALREADY_PROVIDED, surface))); 479 } catch (InterruptedException | ExecutionException e) { 480 executor.execute( 481 () -> resultListener.accept( 482 Result.of(Result.RESULT_WILL_NOT_PROVIDE_SURFACE, surface))); 483 } 484 } 485 } 486 487 /** 488 * Signals that the request will never be fulfilled. 489 * 490 * <p>This may be called in the case where the application may be shutting down and a 491 * surface will never be produced to fulfill the request. 492 * 493 * <p>This should always be called as soon as it is known that the request will not 494 * be fulfilled. Failure to complete the SurfaceRequest via {@code willNotProvideSurface()} 495 * or {@link #provideSurface(Surface, Executor, Consumer)} may cause long delays in shutting 496 * down the camera. 497 * 498 * <p>Upon returning from this method, the request is guaranteed to be complete, regardless 499 * of the return value. If the request was previously successfully completed by 500 * {@link #provideSurface(Surface, Executor, Consumer)}, invoking this method will return 501 * {@code false}, and will have no effect on how the surface is used by the camera. 502 * 503 * @return {@code true} if this call to {@code willNotProvideSurface()} successfully 504 * completes the request, i.e., the request has not already been completed via 505 * {@link #provideSurface(Surface, Executor, Consumer)} or by a previous call to 506 * {@code willNotProvideSurface()} and has not already been cancelled by the camera. 507 */ willNotProvideSurface()508 public boolean willNotProvideSurface() { 509 return mSurfaceCompleter.setException( 510 new DeferrableSurface.SurfaceUnavailableException("Surface request " 511 + "will not complete.")); 512 } 513 514 /** 515 * Sets a {@link Runnable} that handles the situation where {@link Surface} is no longer valid 516 * and triggers the process to request a new {@link Surface}. 517 * 518 * @param executor Executor used to execute the {@code runnable}. 519 * @param runnable The code which will be run when {@link Surface} is no longer valid. 520 */ initialSurfaceRecreationCompleter( @onNull Executor executor, @NonNull Runnable runnable)521 private CallbackToFutureAdapter.Completer<Void> initialSurfaceRecreationCompleter( 522 @NonNull Executor executor, @NonNull Runnable runnable) { 523 AtomicReference<CallbackToFutureAdapter.Completer<Void>> completerRef = 524 new AtomicReference<>(null); 525 final ListenableFuture<Void> future = CallbackToFutureAdapter.getFuture(completer -> { 526 completerRef.set(completer); 527 return "SurfaceRequest-surface-recreation(" + SurfaceRequest.this.hashCode() + ")"; 528 }); 529 530 Futures.addCallback(future, new FutureCallback<Void>() { 531 @Override 532 public void onSuccess(@Nullable Void result) { 533 runnable.run(); 534 } 535 536 @Override 537 public void onFailure(@NonNull Throwable t) { 538 // Do nothing 539 } 540 }, executor); 541 542 return Preconditions.checkNotNull(completerRef.get()); 543 } 544 545 /** 546 * Invalidates the previously provided {@link Surface} to provide a new {@link Surface}. 547 * 548 * <p>Call this method to inform the surface requester that the previously provided 549 * {@link Surface} is no longer valid (e.g. when the SurfaceView destroys its surface due to 550 * page being slid out in ViewPager2) and should re-send a {@link SurfaceRequest} to obtain a 551 * new {@link Surface}. 552 * 553 * <p>Calling this method will cause the camera to be reconfigured. The app should call this 554 * method when the surface provider is ready to provide a new {@link Surface}. (e.g. a 555 * SurfaceView's surface is created when its window is visible.) 556 * 557 * <p>If the provided {@link Surface} was already invalidated, invoking this method will return 558 * {@code false}, and will have no effect. The surface requester will not be notified again, so 559 * there will not be another {@link SurfaceRequest}. 560 * 561 * <p>Calling this method without {@link #provideSurface(Surface, Executor, Consumer)} 562 * (regardless of whether @link #willNotProvideSurface()} has been called) will still trigger 563 * the surface requester to re-send a {@link SurfaceRequest}. 564 * 565 * <p>Since calling this method also means that the {@link SurfaceRequest} will not be 566 * fulfilled, if the {@link SurfaceRequest} has not responded, it will respond as if calling 567 * {@link #willNotProvideSurface()}. 568 * 569 * @return true if the provided {@link Surface} is invalidated or false if it was already 570 * invalidated. 571 */ invalidate()572 public boolean invalidate() { 573 willNotProvideSurface(); 574 return mSurfaceRecreationCompleter.set(null); 575 } 576 577 /** 578 * Adds a listener to be informed when the camera cancels the surface request. 579 * 580 * <p>A surface request may be cancelled by the camera if the surface is no longer required. 581 * Examples of why cancellation may occur include (1) a {@link UseCase} being unbound from the 582 * camera, (2) surface requirements, such as {@linkplain #getResolution() resolution}, changing 583 * due to newly bound use cases, or (3) the camera requiring a new {@link Surface} 584 * object on lower API levels to work around compatibility issues. 585 * 586 * <p>When a request is cancelled, the {@link Runnable Runnables} provided here will be 587 * invoked on the {@link Executor} they are added with, and can be used as a signal to stop any 588 * work that may be in progress to fulfill the surface request. 589 * 590 * <p>Once a surface request has been cancelled by the camera, 591 * {@link #willNotProvideSurface()} will have no effect and will return {@code false}. 592 * Attempting to complete the request via {@link #provideSurface(Surface, Executor, Consumer)} 593 * will also have no effect, and any {@code resultListener} passed to 594 * {@link #provideSurface(Surface, Executor, Consumer)} will be invoked with a {@link Result} 595 * containing {@link Result#RESULT_REQUEST_CANCELLED}. 596 * 597 * <p>Note that due to the asynchronous nature of this listener, it is not guaranteed 598 * that the listener will be called before an attempt to complete the request with 599 * {@link #provideSurface(Surface, Executor, Consumer)} or {@link #willNotProvideSurface()}, so 600 * the return values of these methods can always be checked if your workflow for producing a 601 * surface expects them to complete successfully. 602 * 603 * @param executor The executor used to notify the listener. 604 * @param listener The listener which will be run upon request cancellation. 605 */ 606 // Since registered listeners will only be called once, and the lifetime of a SurfaceRequest 607 // is relatively short, there is no need for a 'removeRequestCancellationListener()' method. 608 // References to listeners are also automatically freed up upon completion of the request due 609 // to the implementation of CallbackToFutureAdapter.Completer. 610 @SuppressLint("PairedRegistration") addRequestCancellationListener(@onNull Executor executor, @NonNull Runnable listener)611 public void addRequestCancellationListener(@NonNull Executor executor, 612 @NonNull Runnable listener) { 613 mRequestCancellationCompleter.addCancellationListener(listener, executor); 614 } 615 616 /** 617 * Updates the {@link TransformationInfo} associated with this {@link SurfaceRequest}. 618 */ 619 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) updateTransformationInfo(@onNull TransformationInfo transformationInfo)620 public void updateTransformationInfo(@NonNull TransformationInfo transformationInfo) { 621 TransformationInfoListener listener; 622 Executor executor; 623 synchronized (mLock) { 624 mTransformationInfo = transformationInfo; 625 listener = mTransformationInfoListener; 626 executor = mTransformationInfoExecutor; 627 } 628 if (listener != null && executor != null) { 629 executor.execute(() -> listener.onTransformationInfoUpdate(transformationInfo)); 630 } 631 } 632 633 /** 634 * Sets a listener to receive updates on transformation info. 635 * 636 * <p> Sets a listener to receive the transformation info associated with this 637 * {@link SurfaceRequest} when it changes or becomes available. The listener is called 638 * immediately if transformation info is available at the time of setting. 639 * 640 * @param executor The executor used to notify the listener. 641 * @param listener the listener which will be called when transformation info changes. 642 * @see TransformationInfoListener 643 * @see TransformationInfo 644 */ setTransformationInfoListener(@onNull Executor executor, @NonNull TransformationInfoListener listener)645 public void setTransformationInfoListener(@NonNull Executor executor, 646 @NonNull TransformationInfoListener listener) { 647 TransformationInfo transformationInfo; 648 synchronized (mLock) { 649 mTransformationInfoListener = listener; 650 mTransformationInfoExecutor = executor; 651 transformationInfo = mTransformationInfo; 652 } 653 if (transformationInfo != null) { 654 executor.execute(() -> listener.onTransformationInfoUpdate(transformationInfo)); 655 } 656 } 657 658 /** 659 * Clears the {@link TransformationInfoListener} set via {@link #setTransformationInfoListener}. 660 */ clearTransformationInfoListener()661 public void clearTransformationInfoListener() { 662 synchronized (mLock) { 663 mTransformationInfoListener = null; 664 mTransformationInfoExecutor = null; 665 } 666 } 667 668 /** 669 * An exception used to signal that the camera has cancelled a request for a {@link Surface}. 670 * 671 * <p>This may be set on the {@link ListenableFuture} returned by 672 * {@link SurfaceRequest#provideSurface(Surface, Executor, Consumer) when the camera is 673 * shutting down or when the surface resolution requirements have changed in order to 674 * accommodate newly bound use cases, in which case the {@linkplain Runnable runnables} 675 * provided to {@link #addRequestCancellationListener(Executor, Runnable)} will also be 676 * invoked on their respective {@link Executor Executors}. 677 */ 678 private static final class RequestCancelledException extends RuntimeException { RequestCancelledException(@onNull String message, @NonNull Throwable cause)679 RequestCancelledException(@NonNull String message, @NonNull Throwable cause) { 680 super(message, cause); 681 } 682 } 683 684 /** 685 * Listener that receives updates of the {@link TransformationInfo} associated with the 686 * {@link SurfaceRequest}. 687 */ 688 public interface TransformationInfoListener { 689 690 /** 691 * Called when the {@link TransformationInfo} is updated. 692 * 693 * <p> This is called when the transformation info becomes available or is updated. 694 * The rotation degrees is updated after calling {@link Preview#setTargetRotation}, and the 695 * crop rect is updated after changing the {@link ViewPort} associated with the 696 * {@link Preview}. 697 * 698 * @param transformationInfo apply the transformation info to transform {@link Preview} 699 * @see TransformationInfo 700 * @see Preview#setTargetRotation(int) 701 * @see Preview.Builder#setTargetRotation(int) 702 * @see CameraCharacteristics#SENSOR_ORIENTATION 703 * @see ViewPort 704 */ onTransformationInfoUpdate(@onNull TransformationInfo transformationInfo)705 void onTransformationInfoUpdate(@NonNull TransformationInfo transformationInfo); 706 } 707 708 /** 709 * Result of providing a surface to a {@link SurfaceRequest} via 710 * {@link #provideSurface(Surface, Executor, Consumer)}. 711 */ 712 @AutoValue 713 public abstract static class Result { 714 715 /** 716 * Possible result codes. 717 */ 718 @IntDef({RESULT_SURFACE_USED_SUCCESSFULLY, RESULT_REQUEST_CANCELLED, RESULT_INVALID_SURFACE, 719 RESULT_SURFACE_ALREADY_PROVIDED, RESULT_WILL_NOT_PROVIDE_SURFACE}) 720 @Retention(RetentionPolicy.SOURCE) 721 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 722 public @interface ResultCode { 723 } 724 725 /** 726 * Provided surface was successfully used by the camera and eventually detached once no 727 * longer needed by the camera. 728 * 729 * <p>This result denotes that it is safe to release the {@link Surface} and any underlying 730 * resources. 731 * 732 * <p>For compatibility reasons, the {@link Surface} object should not be reused by 733 * future {@link SurfaceRequest SurfaceRequests}, and a new surface should be 734 * created instead. 735 */ 736 public static final int RESULT_SURFACE_USED_SUCCESSFULLY = 0; 737 738 /** 739 * Provided surface was never attached to the camera due to the {@link SurfaceRequest} being 740 * cancelled by the camera. 741 * 742 * <p>It is safe to release or reuse {@link Surface}, assuming it was not previously 743 * attached to a camera via {@link #provideSurface(Surface, Executor, Consumer)}. If 744 * reusing the surface for a future surface request, it should be verified that the 745 * surface still matches the resolution specified by {@link SurfaceRequest#getResolution()}. 746 */ 747 public static final int RESULT_REQUEST_CANCELLED = 1; 748 749 /** 750 * Provided surface could not be used by the camera. 751 * 752 * <p>This is likely due to the {@link Surface} being closed prematurely or the resolution 753 * of the surface not matching the resolution specified by 754 * {@link SurfaceRequest#getResolution()}. 755 */ 756 public static final int RESULT_INVALID_SURFACE = 2; 757 758 /** 759 * Surface was not attached to the camera through this invocation of 760 * {@link #provideSurface(Surface, Executor, Consumer)} due to the {@link SurfaceRequest} 761 * already being complete with a surface. 762 * 763 * <p>The {@link SurfaceRequest} has already been completed by a previous invocation 764 * of {@link #provideSurface(Surface, Executor, Consumer)}. 765 * 766 * <p>It is safe to release or reuse the {@link Surface}, assuming it was not previously 767 * attached to a camera via {@link #provideSurface(Surface, Executor, Consumer)}. 768 */ 769 public static final int RESULT_SURFACE_ALREADY_PROVIDED = 3; 770 771 /** 772 * Surface was not attached to the camera through this invocation of 773 * {@link #provideSurface(Surface, Executor, Consumer)} due to the {@link SurfaceRequest} 774 * already being marked as "will not provide surface". 775 * 776 * <p>The {@link SurfaceRequest} has already been marked as 'will not provide surface' by a 777 * previous invocation of {@link #willNotProvideSurface()}. 778 * 779 * <p>It is safe to release or reuse the {@link Surface}, assuming it was not previously 780 * attached to a camera via {@link #provideSurface(Surface, Executor, Consumer)}. 781 */ 782 public static final int RESULT_WILL_NOT_PROVIDE_SURFACE = 4; 783 784 /** 785 * Creates a result from the given result code and surface. 786 * 787 * <p>Can be used to compare to results returned to {@code resultListener} in 788 * {@link #provideSurface(Surface, Executor, Consumer)}. 789 * 790 * @param code One of {@link #RESULT_SURFACE_USED_SUCCESSFULLY}, 791 * {@link #RESULT_REQUEST_CANCELLED}, {@link #RESULT_INVALID_SURFACE}, 792 * {@link #RESULT_SURFACE_ALREADY_PROVIDED}, or 793 * {@link #RESULT_WILL_NOT_PROVIDE_SURFACE}. 794 * @param surface The {@link Surface} used to complete the {@link SurfaceRequest}. 795 */ of(@esultCode int code, @NonNull Surface surface)796 static @NonNull Result of(@ResultCode int code, @NonNull Surface surface) { 797 return new AutoValue_SurfaceRequest_Result(code, surface); 798 } 799 800 /** 801 * Returns the result of invoking {@link #provideSurface(Surface, Executor, Consumer)} 802 * with the surface from {@link #getSurface()}. 803 * 804 * @return One of {@link #RESULT_SURFACE_USED_SUCCESSFULLY}, 805 * {@link #RESULT_REQUEST_CANCELLED}, {@link #RESULT_INVALID_SURFACE}, or 806 * {@link #RESULT_SURFACE_ALREADY_PROVIDED}, {@link #RESULT_WILL_NOT_PROVIDE_SURFACE}. 807 */ 808 @ResultCode getResultCode()809 public abstract int getResultCode(); 810 811 /** 812 * The surface used to complete a {@link SurfaceRequest} with 813 * {@link #provideSurface(Surface, Executor, Consumer)}. 814 * 815 * @return the surface. 816 */ getSurface()817 public abstract @NonNull Surface getSurface(); 818 819 // Ensure Result can't be subclassed outside the package Result()820 Result() { 821 } 822 } 823 824 /** 825 * Transformation associated the preview output. 826 * 827 * <p> The {@link TransformationInfo} can be used transform the {@link Surface} provided via 828 * {@link SurfaceRequest#provideSurface}. The info is based on the camera sensor rotation, 829 * preview target rotation and the {@link ViewPort} associated with the {@link Preview}. The 830 * application of the info depends on the source of the {@link Surface}. For detailed example, 831 * please check out the source code of PreviewView in androidx.camera.view artifact. 832 * 833 * <p> The info is also needed to transform coordinates across use cases. In a face detection 834 * example, one common scenario is running a face detection algorithm against a 835 * {@link ImageAnalysis} use case, and highlight the detected face in the preview. Below is 836 * a code sample to get the transformation {@link Matrix} based on the {@link ImageProxy} from 837 * {@link ImageAnalysis} and the {@link TransformationInfo} from {@link Preview}: 838 * 839 * <pre><code> 840 * // Get rotation transformation. 841 * val transformation = Matrix() 842 * transformation.setRotate(info.getRotationDegrees()) 843 * 844 * // Get rotated crop rect and cropping transformation. 845 * val rotatedRect = new RectF() 846 * rotation.mapRect(rotatedRect, RectF(imageProxy.getCropRect())) 847 * rotatedRect.sort() 848 * val cropTransformation = Matrix() 849 * cropTransformation.setRectToRect( 850 * RectF(imageProxy.getCropRect()), rotatedRect, ScaleToFit.FILL) 851 * 852 * // Concatenate the rotation and cropping transformations. 853 * transformation.postConcat(cropTransformation) 854 * </code></pre> 855 * 856 * @see Preview#setTargetRotation(int) 857 * @see Preview.Builder#setTargetRotation(int) 858 * @see CameraCharacteristics#SENSOR_ORIENTATION 859 * @see ViewPort 860 */ 861 @AutoValue 862 public abstract static class TransformationInfo { 863 864 /** 865 * Returns the crop rect rectangle. 866 * 867 * <p> The returned value dictates how the {@link Surface} provided in 868 * {@link SurfaceRequest#provideSurface} should be displayed. The crop 869 * rectangle specifies the region of valid pixels in the buffer, using coordinates from (0, 870 * 0) to the (width, height) of {@link SurfaceRequest#getResolution}. The caller should 871 * arrange the UI so that only the valid region is visible to app users. 872 * 873 * <p> If {@link Preview} is configured with a {@link ViewPort}, this value is calculated 874 * based on the configuration of {@link ViewPort}; if not, it returns the full rect of the 875 * buffer. For code sample on how to apply the crop rect, please see {@link ViewPort#FIT}. 876 * 877 * @see ViewPort 878 */ getCropRect()879 public abstract @NonNull Rect getCropRect(); 880 881 /** 882 * Returns the rotation needed to transform the output from sensor to the target 883 * rotation. 884 * 885 * <p> This is a clockwise rotation in degrees that needs to be applied to the sensor 886 * buffer. The rotation will be determined by {@link CameraCharacteristics}, 887 * {@link Preview#setTargetRotation(int)} and 888 * {@link Preview.Builder#setTargetRotation(int)}. This value is useful for transforming 889 * coordinates across use cases. 890 * 891 * <p> This value is most useful for transforming coordinates across use cases, e.g. in 892 * preview, highlighting a pattern detected in image analysis. For correcting 893 * the preview itself, usually the source of the {@link Surface} handles the rotation 894 * without needing this value. For {@link SurfaceView}, it automatically corrects the 895 * preview to match the display rotation. For {@link TextureView}, the only additional 896 * rotation needed is the display rotation. For detailed example, please check out the 897 * source code of PreviewView in androidx.camera .view artifact. 898 * 899 * @return The rotation in degrees which will be a value in {0, 90, 180, 270}. 900 * @see Preview#setTargetRotation(int) 901 * @see Preview#getTargetRotation() 902 * @see ViewPort 903 */ 904 @ImageOutputConfig.RotationDegreesValue getRotationDegrees()905 public abstract int getRotationDegrees(); 906 907 /** 908 * The {@linkplain Preview#getTargetRotation() target rotation} of the {@link Preview}. 909 * 910 * <p>Used to correct preview for {@link TextureView}. 911 * {@link #getRotationDegrees()} is a function of 1) 912 * {@link CameraCharacteristics#SENSOR_ORIENTATION}, 2) camera lens facing direction and 3) 913 * target rotation. {@link TextureView} handles 1) & 2) automatically, 914 * while still needs the target rotation to correct the display.This is used when apps 915 * need to rotate the preview to non-display orientation. 916 * 917 * <p>The API is internal for PreviewView to use. For external users, the value 918 * is usually {@link Display#getRotation()} in practice. If that's not the case, they can 919 * always obtain the value from {@link Preview#getTargetRotation()}. 920 * 921 * <p>Please note that if the value is {@link ImageOutputConfig#ROTATION_NOT_SPECIFIED} 922 * which means targetRotation is not specified for Preview, the user should always get 923 * up-to-date display rotation and re-calculate the rotationDegrees to correct the display. 924 * 925 * @see CameraCharacteristics#SENSOR_ORIENTATION 926 */ 927 @ImageOutputConfig.OptionalRotationValue 928 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) getTargetRotation()929 public abstract int getTargetRotation(); 930 931 /** 932 * Whether the {@link Surface} contains the camera transform. 933 * 934 * <p>When the Surface is connected to the camera directly, camera writes the 935 * camera orientation value to the Surface. For example, the value can be retrieved via 936 * {@link SurfaceTexture#getTransformMatrix(float[])}. Android components such 937 * as {@link TextureView} and {@link SurfaceView} use the value to transform the output. 938 * When the Surface is not connect to the camera directly, for example, when it was 939 * copied with OpenGL, the Surface will not contain the camera orientation value. 940 * 941 * <p>The app may need to transform the UI differently based on this flag. If this value 942 * is true, the app only needs to apply the Surface transformation; otherwise, the app 943 * needs to apply the value of {@link #getRotationDegrees()}. For example, if the preview 944 * is displayed in a {@link TextureView}: 945 * 946 * <pre><code> 947 * int rotationDegrees; 948 * if (surfaceRequest.hasCameraTransform()) { 949 * switch (textureView.getDisplay().getRotation()) { 950 * case Surface.ROTATION_0: 951 * rotationDegrees = 0; 952 * break; 953 * case Surface.ROTATION_90: 954 * rotationDegrees = 90; 955 * break; 956 * case Surface.ROTATION_180: 957 * rotationDegrees = 180; 958 * break; 959 * case Surface.ROTATION_270: 960 * rotationDegrees = 270; 961 * break; 962 * } 963 * } else { 964 * rotationDegrees = transformationInfo.getRotationDegrees(); 965 * } 966 * Matrix textureViewTransform = new Matrix(); 967 * textureViewTransform.postRotate(rotationDegrees); 968 * textureView.setTransform(textureViewTransform); 969 * </code></pre> 970 * 971 * @return true if the {@link Surface} contains the camera transformation. 972 */ hasCameraTransform()973 public abstract boolean hasCameraTransform(); 974 975 /** 976 * Returns the sensor to image buffer transform matrix. 977 * 978 * <p>The value is a mapping from sensor coordinates to buffer coordinates, which is, 979 * from the rect of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE} to the 980 * rect defined by {@code (0, 0, #getResolution#getWidth(), #getResolution#getHeight())}. 981 * The matrix can be used to map the coordinates from one {@link UseCase} to another. For 982 * example, detecting face with {@link ImageAnalysis}, and then highlighting the face in 983 * {@link Preview}. 984 * 985 * <p>Code sample 986 * <code><pre> 987 * // Get the transformation from sensor to effect input. 988 * Matrix sensorToEffect = surfaceRequest.getSensorToBufferTransform(); 989 * // Get the transformation from sensor to ImageAnalysis. 990 * Matrix sensorToAnalysis = imageProxy.getSensorToBufferTransform(); 991 * // Concatenate the two matrices to get the transformation from ImageAnalysis to effect. 992 * Matrix analysisToEffect = Matrix() 993 * sensorToAnalysis.invert(analysisToEffect); 994 * analysisToEffect.postConcat(sensorToEffect); 995 * </pre></code> 996 */ getSensorToBufferTransform()997 public abstract @NonNull Matrix getSensorToBufferTransform(); 998 999 /** 1000 * Returns whether the buffer should be mirrored. 1001 * 1002 * <p>This flag indicates whether the buffer needs to be mirrored across the vertical 1003 * axis. For example, for front camera preview, the buffer should usually be mirrored. The 1004 * mirroring should be applied after the {@link #getRotationDegrees()} is applied. 1005 */ isMirroring()1006 public abstract boolean isMirroring(); 1007 1008 /** 1009 * Creates new {@link TransformationInfo} 1010 * 1011 * <p> Internally public to be used in view artifact tests. 1012 */ 1013 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) of(@onNull Rect cropRect, @ImageOutputConfig.RotationDegreesValue int rotationDegrees, @ImageOutputConfig.OptionalRotationValue int targetRotation, boolean hasCameraTransform, @NonNull Matrix sensorToBufferTransform, boolean mirroring)1014 public static @NonNull TransformationInfo of(@NonNull Rect cropRect, 1015 @ImageOutputConfig.RotationDegreesValue int rotationDegrees, 1016 @ImageOutputConfig.OptionalRotationValue int targetRotation, 1017 boolean hasCameraTransform, @NonNull Matrix sensorToBufferTransform, 1018 boolean mirroring) { 1019 return new AutoValue_SurfaceRequest_TransformationInfo(cropRect, rotationDegrees, 1020 targetRotation, hasCameraTransform, sensorToBufferTransform, mirroring); 1021 } 1022 1023 // Hides public constructor. TransformationInfo()1024 TransformationInfo() { 1025 } 1026 } 1027 } 1028