1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.camera.camera2.pipe
18 
19 import androidx.annotation.RestrictTo
20 import androidx.camera.camera2.pipe.core.Debug
21 
22 /**
23  * An ordered list of [TCaptureRequest] objects, listeners, and associated metadata that will be
24  * submitted and captured together when submitted to the camera.
25  *
26  * A CaptureSequence should be created from a [CaptureSequenceProcessor].
27  */
28 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
29 public interface CaptureSequence<out TCaptureRequest> {
30     public val cameraId: CameraId
31     public val repeating: Boolean
32     public val captureRequestList: List<TCaptureRequest>
33     public val captureMetadataList: List<RequestMetadata>
34     public val listeners: List<Request.Listener>
35     public val sequenceListener: CaptureSequenceListener
36 
37     /** This value must be set to the return value of [CaptureSequenceProcessor.submit] */
38     public var sequenceNumber: Int
39 
40     public interface CaptureSequenceListener {
onCaptureSequenceCompletenull41         public fun onCaptureSequenceComplete(captureSequence: CaptureSequence<*>)
42     }
43 }
44 
45 /** Utility functions for interacting with [CaptureSequence] callbacks and listeners. */
46 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
47 public object CaptureSequences {
48     /**
49      * Efficient, inlined utility function for invoking a call on each of the listeners defined on a
50      * [CaptureSequence] instance using the provided [RequestMetadata] object.
51      */
52     public inline fun <T> CaptureSequence<T>.invokeOnRequests(
53         crossinline fn: (RequestMetadata, Int, Request.Listener) -> Any
54     ) {
55         Debug.traceStart { "InvokeInternalListeners" }
56         // Always invoke the internal listener first on all of the internal listeners for the
57         // entire sequence before invoking the listeners specified in the specific requests
58         for (i in captureMetadataList.indices) {
59             val request = captureMetadataList[i]
60             for (listenerIndex in listeners.indices) {
61                 fn(request, i, listeners[listenerIndex])
62             }
63         }
64 
65         Debug.traceStop()
66         Debug.traceStart { "InvokeRequestListeners" }
67 
68         // Invoke the listeners that were defined on the individual requests.
69         for (i in captureMetadataList.indices) {
70             val request = captureMetadataList[i]
71             for (listenerIndex in request.request.listeners.indices) {
72                 fn(request, i, request.request.listeners[listenerIndex])
73             }
74         }
75 
76         Debug.traceStop()
77     }
78 
79     /**
80      * Efficient, inlined utility function for invoking a call on each of the listeners defined on a
81      * [CaptureSequence] instance using the provided [RequestMetadata] object.
82      */
83     public inline fun <T> CaptureSequence<T>.invokeOnRequest(
84         request: RequestMetadata,
85         crossinline fn: (Request.Listener) -> Any
86     ) {
87         Debug.traceStart { "InvokeInternalListeners" }
88 
89         // Always invoke the sequence listeners first so that internal state can be updated before
90         // specific requests receive the callback.
91         for (i in listeners.indices) {
92             fn(listeners[i])
93         }
94 
95         Debug.traceStop()
96         Debug.traceStart { "InvokeRequestListeners" }
97 
98         // Invoke the listeners that were defined on this request.
99         for (i in request.request.listeners.indices) {
100             fn(request.request.listeners[i])
101         }
102 
103         Debug.traceStop()
104     }
105 }
106