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