1 /*
2  * Copyright 2024 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.testing
18 
19 import android.util.Size
20 import android.view.Surface
21 import androidx.annotation.GuardedBy
22 import androidx.camera.camera2.pipe.CameraStream
23 import androidx.camera.camera2.pipe.ImageSourceConfig
24 import androidx.camera.camera2.pipe.OutputId
25 import androidx.camera.camera2.pipe.StreamFormat
26 import androidx.camera.camera2.pipe.StreamId
27 import androidx.camera.camera2.pipe.media.ImageReaderWrapper
28 
29 /**
30  * Utility class for creating, tracking, and simulating [FakeImageReader]s. ImageReaders can be
31  * retrieved based on [Surface] or by [StreamId], and supports both single and
32  * MultiResolutionImageReader-like implementations.
33  */
34 public class FakeImageReaders(private val fakeSurfaces: FakeSurfaces) {
35     private val lock = Any()
36 
37     @GuardedBy("lock") private val fakeImageReaders = mutableListOf<FakeImageReader>()
38 
getnull39     public operator fun get(surface: Surface): FakeImageReader? {
40         return synchronized(lock) { fakeImageReaders.find { it.surface == surface } }
41     }
42 
getnull43     public operator fun get(streamId: StreamId): FakeImageReader? {
44         return synchronized(lock) { fakeImageReaders.find { it.streamId == streamId } }
45     }
46 
47     /** Create a [FakeImageReader] based on a single [CameraStream]. */
createnull48     public fun create(cameraStream: CameraStream, capacity: Int): FakeImageReader =
49         create(
50             cameraStream.outputs.first().format,
51             cameraStream.id,
52             cameraStream.outputs.associate { it.id to it.size },
53             capacity
54         )
55 
56     /** Create a [FakeImageReader] from its properties. */
createnull57     public fun create(
58         format: StreamFormat,
59         streamId: StreamId,
60         outputIdMap: Map<OutputId, Size>,
61         capacity: Int,
62         fakeSurfaces: FakeSurfaces? = null
63     ): FakeImageReader {
64         check(this[streamId] == null) {
65             "Cannot create multiple ImageReader(s) from the same $streamId!"
66         }
67 
68         val fakeImageReader =
69             FakeImageReader.create(format, streamId, outputIdMap, capacity, fakeSurfaces)
70         synchronized(lock) { fakeImageReaders.add(fakeImageReader) }
71         return fakeImageReader
72     }
73 
74     /** Create a [FakeImageReader] based on a [CameraStream] and an [ImageSourceConfig]. */
createnull75     public fun create(
76         cameraStream: CameraStream,
77         imageSourceConfig: ImageSourceConfig
78     ): ImageReaderWrapper =
79         create(
80             cameraStream.outputs.first().format,
81             cameraStream.id,
82             cameraStream.outputs.associate { it.id to it.size },
83             imageSourceConfig.capacity,
84             fakeSurfaces
85         )
86 
87     /** [check] that all [FakeImageReader]s are closed. */
checkImageReadersClosednull88     public fun checkImageReadersClosed() {
89         for (fakeImageReader in fakeImageReaders) {
90             check(fakeImageReader.isClosed) { "Failed to close ImageReader: $fakeImageReader" }
91         }
92     }
93 
94     /** [check] that all images from all [FakeImageReader]s are closed. */
checkImagesClosednull95     public fun checkImagesClosed() {
96         for (fakeImageReader in fakeImageReaders) {
97             fakeImageReader.checkImagesClosed()
98         }
99     }
100 }
101