Cleanup CameraExtensionMetadata and bring it up to date.
- Add a dedicated FakeCameraExtensionMetadata implementation
- Add utility functions for Lazy value properties
- Remove Camera2 types from the CameraMetadataProvider
- Integrate FakeExtensionMetadata into FakeCameraMetadata
- Cleanup several TODOs
- Replaced several TODO() functions with explicit exceptions
Test: ./gradlew\
:camera:camera-camera2-pipe:testDebugUnitTest\
:camera:camera-camera2-pipe-testing:testDebugUnitTest\
:camera:camera-camera2-pipe-integration:testDebugUnitTest
Change-Id: I641944263b06481243244d51665fb3213e8b4142
diff --git a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraMetadata.kt b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraMetadata.kt
index 359a02d..5c92fb2 100644
--- a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraMetadata.kt
+++ b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraMetadata.kt
@@ -21,20 +21,11 @@
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CaptureRequest
import android.hardware.camera2.CaptureResult
-import android.hardware.camera2.TotalCaptureResult
-import android.view.Surface
+import android.util.Size
import androidx.camera.camera2.pipe.CameraExtensionMetadata
import androidx.camera.camera2.pipe.CameraId
import androidx.camera.camera2.pipe.CameraMetadata
-import androidx.camera.camera2.pipe.FrameInfo
-import androidx.camera.camera2.pipe.FrameMetadata
-import androidx.camera.camera2.pipe.FrameNumber
import androidx.camera.camera2.pipe.Metadata
-import androidx.camera.camera2.pipe.Request
-import androidx.camera.camera2.pipe.RequestMetadata
-import androidx.camera.camera2.pipe.RequestNumber
-import androidx.camera.camera2.pipe.RequestTemplate
-import androidx.camera.camera2.pipe.StreamId
import kotlin.reflect.KClass
import kotlinx.atomicfu.atomic
@@ -43,15 +34,6 @@
internal fun nextFakeCameraId(): CameraId =
CameraId("FakeCamera-${fakeCameraIds.incrementAndGet()}")
-private val fakeRequestNumbers = atomic(0L)
-
-internal fun nextFakeRequestNumber(): RequestNumber =
- RequestNumber(fakeRequestNumbers.incrementAndGet())
-
-private val fakeFrameNumbers = atomic(0L)
-
-internal fun nextFakeFrameNumber(): FrameNumber = FrameNumber(fakeFrameNumbers.incrementAndGet())
-
/** Utility class for interacting with objects that require pre-populated Metadata. */
open class FakeMetadata(private val metadata: Map<Metadata.Key<*>, Any?> = emptyMap()) : Metadata {
companion object {
@@ -79,7 +61,7 @@
override val sessionKeys: Set<CaptureRequest.Key<*>> = emptySet(),
val physicalMetadata: Map<CameraId, CameraMetadata> = emptyMap(),
override val physicalRequestKeys: Set<CaptureRequest.Key<*>> = emptySet(),
- override val supportedExtensions: Set<Int> = emptySet(),
+ private val extensions: Map<Int, FakeCameraExtensionMetadata> = emptyMap(),
) : FakeMetadata(metadata), CameraMetadata {
override fun <T> get(key: CameraCharacteristics.Key<T>): T? = characteristics[key] as T?
@@ -91,6 +73,8 @@
override val isRedacted: Boolean = false
override val physicalCameraIds: Set<CameraId> = physicalMetadata.keys
+ override val supportedExtensions: Set<Int>
+ get() = extensions.keys
override suspend fun getPhysicalMetadata(cameraId: CameraId): CameraMetadata =
physicalMetadata[cameraId]!!
@@ -99,11 +83,11 @@
physicalMetadata[cameraId]!!
override suspend fun getExtensionMetadata(extension: Int): CameraExtensionMetadata {
- TODO("b/299356087 - Add support for fake extension metadata")
+ return extensions[extension]!!
}
override fun awaitExtensionMetadata(extension: Int): CameraExtensionMetadata {
- TODO("b/299356087 - Add support for fake extension metadata")
+ return extensions[extension]!!
}
override fun <T : Any> unwrapAs(type: KClass<T>): T? = null
@@ -111,81 +95,43 @@
override fun toString(): String = "FakeCameraMetadata(camera: ${camera.value})"
}
-/** Utility class for interacting with objects require specific [CaptureRequest] metadata. */
-class FakeRequestMetadata(
- private val requestParameters: Map<CaptureRequest.Key<*>, Any?> = emptyMap(),
+/** Utility class for interacting with objects require [CameraExtensionMetadata] */
+class FakeCameraExtensionMetadata(
+ override val camera: CameraId,
+ override val cameraExtension: Int,
metadata: Map<Metadata.Key<*>, Any?> = emptyMap(),
- override val template: RequestTemplate = RequestTemplate(0),
- override val streams: Map<StreamId, Surface> = mapOf(),
- override val repeating: Boolean = false,
- override val request: Request = Request(listOf()),
- override val requestNumber: RequestNumber = nextFakeRequestNumber()
-) : FakeMetadata(request.extras.plus(metadata)), RequestMetadata {
-
- override fun <T> get(key: CaptureRequest.Key<T>): T? = requestParameters[key] as T?
-
- override fun <T> getOrDefault(key: CaptureRequest.Key<T>, default: T): T = get(key) ?: default
-
- override fun <T : Any> unwrapAs(type: KClass<T>): T? = null
-
- companion object {
- /** Initialize FakeRequestMetadata based on a specific [Request] object. */
- fun from(
- request: Request,
- streamToSurfaces: Map<StreamId, Surface>,
- repeating: Boolean = false
- ): FakeRequestMetadata {
- check(streamToSurfaces.keys.containsAll(request.streams))
- return FakeRequestMetadata(
- requestParameters = request.parameters,
- template = request.template ?: RequestTemplate(0),
- streams = request.streams.map { it to streamToSurfaces[it]!! }.toMap(),
- repeating = repeating,
- request = request
- )
- }
+ private val characteristics: Map<CameraCharacteristics.Key<*>, Any?> = emptyMap(),
+ override val requestKeys: Set<CaptureRequest.Key<*>> = emptySet(),
+ override val resultKeys: Set<CaptureResult.Key<*>> = emptySet(),
+ private val captureOutputSizes: Map<Int, Set<Size>> = emptyMap(),
+ private val previewOutputSizes: Map<Class<*>, Set<Size>> = emptyMap(),
+ private val postviewSizes: Map<Int, Map<Size, Set<Size>>> = emptyMap(),
+ override val isRedacted: Boolean = false,
+ override val isPostviewSupported: Boolean = false,
+ override val isCaptureProgressSupported: Boolean = false
+) : FakeMetadata(metadata), CameraExtensionMetadata {
+ override fun getOutputSizes(imageFormat: Int): Set<Size> {
+ return captureOutputSizes[imageFormat] ?: emptySet()
}
- override fun toString(): String =
- "FakeRequestMetadata(requestNumber: ${requestNumber.value}, request: $request)"
-}
+ override fun getOutputSizes(klass: Class<*>): Set<Size> {
+ return previewOutputSizes[klass] ?: emptySet()
+ }
-/** Utility class for interacting with objects require specific [CaptureResult] metadata */
-class FakeFrameMetadata(
- private val resultMetadata: Map<CaptureResult.Key<*>, Any?> = emptyMap(),
- extraResultMetadata: Map<Metadata.Key<*>, Any?> = emptyMap(),
- override val camera: CameraId = nextFakeCameraId(),
- override val frameNumber: FrameNumber = nextFakeFrameNumber(),
- override val extraMetadata: Map<*, Any?> = emptyMap<Any, Any>()
-) : FakeMetadata(extraResultMetadata), FrameMetadata {
+ override fun getPostviewSizes(captureSize: Size, format: Int): Set<Size> {
+ return postviewSizes[format]?.get(captureSize) ?: emptySet()
+ }
- override fun <T> get(key: CaptureResult.Key<T>): T? =
- extraMetadata[key] as T? ?: resultMetadata[key] as T?
+ override fun <T> get(key: CameraCharacteristics.Key<T>): T? = characteristics[key] as T?
- override fun <T> getOrDefault(key: CaptureResult.Key<T>, default: T): T = get(key) ?: default
+ override fun <T> getOrDefault(key: CameraCharacteristics.Key<T>, default: T): T =
+ get(key) ?: default
+
+ override val keys: Set<CameraCharacteristics.Key<*>>
+ get() = characteristics.keys
override fun <T : Any> unwrapAs(type: KClass<T>): T? = null
override fun toString(): String =
- "FakeFrameMetadata(camera: ${camera.value}, frameNumber: ${frameNumber.value})"
-}
-
-/** Utility class for interacting with objects require specific [TotalCaptureResult] metadata */
-class FakeFrameInfo(
- override val metadata: FrameMetadata = FakeFrameMetadata(),
- override val requestMetadata: RequestMetadata = FakeRequestMetadata(),
- private val physicalMetadata: Map<CameraId, FrameMetadata> = emptyMap()
-) : FrameInfo {
- override fun get(camera: CameraId): FrameMetadata? = physicalMetadata[camera]
-
- override val camera: CameraId
- get() = metadata.camera
-
- override val frameNumber: FrameNumber
- get() = metadata.frameNumber
-
- override fun <T : Any> unwrapAs(type: KClass<T>): T? = null
-
- override fun toString(): String =
- "FakeFrameInfo(camera: ${camera.value}, frameNumber: ${frameNumber.value})"
+ "FakeCameraExtensionMetadata(camera: ${camera.value}, extension: $cameraExtension)"
}
diff --git a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeFrameMetadata.kt b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeFrameMetadata.kt
new file mode 100644
index 0000000..0eac745
--- /dev/null
+++ b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeFrameMetadata.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe.testing
+
+import android.hardware.camera2.CaptureResult
+import android.hardware.camera2.TotalCaptureResult
+import androidx.camera.camera2.pipe.CameraId
+import androidx.camera.camera2.pipe.FrameInfo
+import androidx.camera.camera2.pipe.FrameMetadata
+import androidx.camera.camera2.pipe.FrameNumber
+import androidx.camera.camera2.pipe.Metadata
+import androidx.camera.camera2.pipe.RequestMetadata
+import kotlin.reflect.KClass
+import kotlinx.atomicfu.atomic
+
+private val fakeFrameNumbers = atomic(0L)
+
+internal fun nextFakeFrameNumber(): FrameNumber = FrameNumber(fakeFrameNumbers.incrementAndGet())
+
+/** Utility class for interacting with objects require specific [CaptureResult] metadata */
+class FakeFrameMetadata(
+ private val resultMetadata: Map<CaptureResult.Key<*>, Any?> = emptyMap(),
+ extraResultMetadata: Map<Metadata.Key<*>, Any?> = emptyMap(),
+ override val camera: CameraId = nextFakeCameraId(),
+ override val frameNumber: FrameNumber = nextFakeFrameNumber(),
+ override val extraMetadata: Map<*, Any?> = emptyMap<Any, Any>()
+) : FakeMetadata(extraResultMetadata), FrameMetadata {
+
+ @Suppress("UNCHECKED_CAST")
+ override fun <T> get(key: CaptureResult.Key<T>): T? =
+ extraMetadata[key] as T? ?: resultMetadata[key] as T?
+
+ override fun <T> getOrDefault(key: CaptureResult.Key<T>, default: T): T = get(key) ?: default
+
+ override fun <T : Any> unwrapAs(type: KClass<T>): T? = null
+
+ override fun toString(): String =
+ "FakeFrameMetadata(camera: ${camera.value}, frameNumber: ${frameNumber.value})"
+}
+
+/** Utility class for interacting with objects require specific [TotalCaptureResult] metadata */
+class FakeFrameInfo(
+ override val metadata: FrameMetadata = FakeFrameMetadata(),
+ override val requestMetadata: RequestMetadata = FakeRequestMetadata(),
+ private val physicalMetadata: Map<CameraId, FrameMetadata> = emptyMap()
+) : FrameInfo {
+ override fun get(camera: CameraId): FrameMetadata? = physicalMetadata[camera]
+
+ override val camera: CameraId
+ get() = metadata.camera
+
+ override val frameNumber: FrameNumber
+ get() = metadata.frameNumber
+
+ override fun <T : Any> unwrapAs(type: KClass<T>): T? = null
+
+ override fun toString(): String =
+ "FakeFrameInfo(camera: ${camera.value}, frameNumber: ${frameNumber.value})"
+}
diff --git a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeRequestMetadata.kt b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeRequestMetadata.kt
new file mode 100644
index 0000000..d522939
--- /dev/null
+++ b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeRequestMetadata.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe.testing
+
+import android.hardware.camera2.CaptureRequest
+import android.view.Surface
+import androidx.camera.camera2.pipe.Metadata
+import androidx.camera.camera2.pipe.Request
+import androidx.camera.camera2.pipe.RequestMetadata
+import androidx.camera.camera2.pipe.RequestNumber
+import androidx.camera.camera2.pipe.RequestTemplate
+import androidx.camera.camera2.pipe.StreamId
+import kotlin.reflect.KClass
+import kotlinx.atomicfu.atomic
+
+private val fakeRequestNumbers = atomic(0L)
+
+internal fun nextFakeRequestNumber(): RequestNumber =
+ RequestNumber(fakeRequestNumbers.incrementAndGet())
+
+/** Utility class for interacting with objects require specific [CaptureRequest] metadata. */
+class FakeRequestMetadata(
+ private val requestParameters: Map<CaptureRequest.Key<*>, Any?> = emptyMap(),
+ metadata: Map<Metadata.Key<*>, Any?> = emptyMap(),
+ override val template: RequestTemplate = RequestTemplate(0),
+ override val streams: Map<StreamId, Surface> = mapOf(),
+ override val repeating: Boolean = false,
+ override val request: Request = Request(listOf()),
+ override val requestNumber: RequestNumber = nextFakeRequestNumber()
+) : FakeMetadata(request.extras.plus(metadata)), RequestMetadata {
+
+ @Suppress("UNCHECKED_CAST")
+ override fun <T> get(key: CaptureRequest.Key<T>): T? = requestParameters[key] as T?
+
+ override fun <T> getOrDefault(key: CaptureRequest.Key<T>, default: T): T = get(key) ?: default
+
+ override fun <T : Any> unwrapAs(type: KClass<T>): T? = null
+
+ companion object {
+ /** Initialize FakeRequestMetadata based on a specific [Request] object. */
+ fun from(
+ request: Request,
+ streamToSurfaces: Map<StreamId, Surface>,
+ repeating: Boolean = false
+ ): FakeRequestMetadata {
+ check(streamToSurfaces.keys.containsAll(request.streams))
+ return FakeRequestMetadata(
+ requestParameters = request.parameters,
+ template = request.template ?: RequestTemplate(0),
+ streams = request.streams.map { it to streamToSurfaces[it]!! }.toMap(),
+ repeating = repeating,
+ request = request
+ )
+ }
+ }
+
+ override fun toString(): String =
+ "FakeRequestMetadata(requestNumber: ${requestNumber.value}, request: $request)"
+}
diff --git a/camera/camera-camera2-pipe-testing/src/test/java/androidx/camera/camera2/pipe/testing/CameraGraphSimulatorTest.kt b/camera/camera-camera2-pipe-testing/src/test/java/androidx/camera/camera2/pipe/testing/CameraGraphSimulatorTest.kt
index f0cf2e8..fe5b689 100644
--- a/camera/camera-camera2-pipe-testing/src/test/java/androidx/camera/camera2/pipe/testing/CameraGraphSimulatorTest.kt
+++ b/camera/camera-camera2-pipe-testing/src/test/java/androidx/camera/camera2/pipe/testing/CameraGraphSimulatorTest.kt
@@ -58,7 +58,8 @@
private val testScope = TestScope()
private val metadata =
FakeCameraMetadata(
- mapOf(CameraCharacteristics.LENS_FACING to CameraCharacteristics.LENS_FACING_FRONT)
+ characteristics =
+ mapOf(CameraCharacteristics.LENS_FACING to CameraCharacteristics.LENS_FACING_FRONT)
)
private val streamConfig = CameraStream.Config.create(Size(640, 480), StreamFormat.YUV_420_888)
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraExtensionMetadata.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraExtensionMetadata.kt
index db923ec..160b1f3 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraExtensionMetadata.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraExtensionMetadata.kt
@@ -14,15 +14,13 @@
* limitations under the License.
*/
-@file:RequiresApi(31) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-
package androidx.camera.camera2.pipe
+import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraExtensionCharacteristics
import android.hardware.camera2.CaptureRequest
import android.hardware.camera2.CaptureResult
import android.util.Size
-import androidx.annotation.RequiresApi
import androidx.annotation.RestrictTo
/**
@@ -37,17 +35,27 @@
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
interface CameraExtensionMetadata : Metadata, UnsafeWrapper {
- val camera: CameraId
- val isRedacted: Boolean
- val cameraExtension: Int
- val isPostviewSupported: Boolean
+ operator fun <T> get(key: CameraCharacteristics.Key<T>): T?
+ fun <T> getOrDefault(key: CameraCharacteristics.Key<T>, default: T): T
+
+ val camera: CameraId
+ val cameraExtension: Int
+
+ val isRedacted: Boolean
+ val isPostviewSupported: Boolean
+ val isCaptureProgressSupported: Boolean
+
+ val keys: Set<CameraCharacteristics.Key<*>>
val requestKeys: Set<CaptureRequest.Key<*>>
val resultKeys: Set<CaptureResult.Key<*>>
+ /** Get output sizes that can be used for high-quality capture requests. */
fun getOutputSizes(imageFormat: Int): Set<Size>
+ /** Get output sizes that can be used for repeating preview requests. */
fun getOutputSizes(klass: Class<*>): Set<Size>
+ /** Get sizes that may be used for the postview stream. */
fun getPostviewSizes(captureSize: Size, format: Int): Set<Size>
}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ApiCompat.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ApiCompat.kt
index 781ba85..3ab4eb5 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ApiCompat.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ApiCompat.kt
@@ -497,6 +497,12 @@
): Boolean = extensionCharacteristics.isPostviewAvailable(extension)
@JvmStatic
+ fun isCaptureProcessProgressAvailable(
+ extensionCharacteristics: CameraExtensionCharacteristics,
+ extension: Int
+ ): Boolean = extensionCharacteristics.isCaptureProcessProgressAvailable(extension)
+
+ @JvmStatic
fun getPostviewSupportedSizes(
extensionCharacteristics: CameraExtensionCharacteristics,
extension: Int,
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraExtensionMetadata.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraExtensionMetadata.kt
index 26b11b3..bb778e1 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraExtensionMetadata.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraExtensionMetadata.kt
@@ -16,6 +16,7 @@
package androidx.camera.camera2.pipe.compat
+import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraExtensionCharacteristics
import android.hardware.camera2.CaptureRequest
import android.hardware.camera2.CaptureResult
@@ -26,8 +27,8 @@
import androidx.camera.camera2.pipe.CameraExtensionMetadata
import androidx.camera.camera2.pipe.CameraId
import androidx.camera.camera2.pipe.Metadata
-import androidx.camera.camera2.pipe.core.Debug
-import androidx.camera.camera2.pipe.core.Log
+import androidx.camera.camera2.pipe.core.lazyOrEmptySet
+import androidx.camera.camera2.pipe.core.lazyOrFalse
import kotlin.reflect.KClass
/**
@@ -36,7 +37,6 @@
* This allows all fields to be accessed and return reasonable values on all OS versions.
*/
@RequiresApi(Build.VERSION_CODES.S)
-// TODO(b/200306659): Remove and replace with annotation on package-info.java
internal class Camera2CameraExtensionMetadata(
override val camera: CameraId,
override val isRedacted: Boolean,
@@ -53,9 +53,16 @@
@GuardedBy("supportedPostviewSizes")
private val supportedPostviewSizes = mutableMapOf<Size, Lazy<Set<Size>>>()
- // TODO: b/299356087 - this here may need a switch statement on the key
+ override fun <T> get(key: CameraCharacteristics.Key<T>): T? {
+ return null // TODO: Add support for this when VIC can be targeted in AndroidX
+ }
+
@Suppress("UNCHECKED_CAST") override fun <T> get(key: Metadata.Key<T>): T? = metadata[key] as T?
+ override fun <T> getOrDefault(key: CameraCharacteristics.Key<T>, default: T): T {
+ return default // TODO: Add support for this when VIC can be targeted in AndroidX
+ }
+
@Suppress("UNCHECKED_CAST")
override fun <T> getOrDefault(key: Metadata.Key<T>, default: T): T =
metadata[key] as T? ?: default
@@ -70,6 +77,12 @@
override val isPostviewSupported: Boolean
get() = _isPostviewSupported.value
+ override val isCaptureProgressSupported: Boolean
+ get() = _isCaptureProgressSupported.value
+
+ override val keys: Set<CameraCharacteristics.Key<*>>
+ get() = emptySet() // TODO: Add support for this when VIC can be targeted in AndroidX
+
override val requestKeys: Set<CaptureRequest.Key<*>>
get() = _requestKeys.value
@@ -77,10 +90,10 @@
get() = _resultKeys.value
override fun getOutputSizes(imageFormat: Int): Set<Size> {
- val supportedExtensionSizes =
+ val lazySizes =
synchronized(supportedExtensionSizesByFormat) {
supportedExtensionSizesByFormat.getOrPut(imageFormat) {
- lazy(LazyThreadSafetyMode.PUBLICATION) {
+ lazyOrEmptySet({ "$camera#getExtensionSupportedSizes(${imageFormat})" }) {
Api31Compat.getExtensionSupportedSizes(
extensionCharacteristics,
cameraExtension,
@@ -90,14 +103,14 @@
}
}
}
- return supportedExtensionSizes.value
+ return lazySizes.value
}
override fun getOutputSizes(klass: Class<*>): Set<Size> {
- val supportedExtensionSizes =
+ val lazySizes =
synchronized(supportedExtensionSizesByClass) {
supportedExtensionSizesByClass.getOrPut(klass) {
- lazy(LazyThreadSafetyMode.PUBLICATION) {
+ lazyOrEmptySet("$camera#getExtensionSupportedSizes(${klass.name})") {
Api31Compat.getExtensionSupportedSizes(
extensionCharacteristics,
cameraExtension,
@@ -107,82 +120,71 @@
}
}
}
- return supportedExtensionSizes.value
+ return lazySizes.value
}
override fun getPostviewSizes(captureSize: Size, format: Int): Set<Size> {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
- val supportedPostviewSizes =
- synchronized(supportedPostviewSizes) {
- supportedPostviewSizes.getOrPut(captureSize) {
- lazy(LazyThreadSafetyMode.PUBLICATION) {
- Api34Compat.getPostviewSupportedSizes(
- extensionCharacteristics,
- cameraExtension,
- captureSize,
- format
- )
- .toSet()
- }
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ return emptySet()
+ }
+
+ val lazySizes =
+ synchronized(supportedPostviewSizes) {
+ supportedPostviewSizes.getOrPut(captureSize) {
+ lazyOrEmptySet("$camera#getPostviewSupportedSizes($captureSize, $format)") {
+ Api34Compat.getPostviewSupportedSizes(
+ extensionCharacteristics,
+ cameraExtension,
+ captureSize,
+ format
+ )
+ .toSet()
}
}
- return supportedPostviewSizes.value
- }
- return emptySet()
+ }
+ return lazySizes.value
}
private val _requestKeys: Lazy<Set<CaptureRequest.Key<*>>> =
- lazy(LazyThreadSafetyMode.PUBLICATION) {
- try {
- Debug.trace("Camera-$camera#availableCaptureRequestKeys") {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- Api33Compat.getAvailableCaptureRequestKeys(
- extensionCharacteristics,
- cameraExtension
- )
- .toSet()
- } else {
- emptySet()
- }
- }
- } catch (e: AssertionError) {
- Log.warn(e) { "Failed to getAvailableCaptureRequestKeys from Camera-$camera" }
+ lazyOrEmptySet({ "$camera#availableCaptureRequestKeys" }) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ Api33Compat.getAvailableCaptureRequestKeys(
+ extensionCharacteristics,
+ cameraExtension
+ )
+ .toSet()
+ } else {
emptySet()
}
}
private val _resultKeys: Lazy<Set<CaptureResult.Key<*>>> =
- lazy(LazyThreadSafetyMode.PUBLICATION) {
- try {
- Debug.trace("Camera-$camera#availableCaptureResultKeys") {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- Api33Compat.getAvailableCaptureResultKeys(
- extensionCharacteristics,
- cameraExtension
- )
- .toSet()
- } else {
- emptySet()
- }
- }
- } catch (e: AssertionError) {
- Log.warn(e) { "Failed to getAvailableCaptureResultKeys from Camera-$camera" }
+ lazyOrEmptySet({ "$camera#availableCaptureResultKeys" }) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ Api33Compat.getAvailableCaptureResultKeys(extensionCharacteristics, cameraExtension)
+ .toSet()
+ } else {
emptySet()
}
}
private val _isPostviewSupported: Lazy<Boolean> =
- lazy(LazyThreadSafetyMode.PUBLICATION) {
- try {
- Debug.trace("Camera-$camera#isPostviewSupported") {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
- Api34Compat.isPostviewAvailable(extensionCharacteristics, cameraExtension)
- } else {
- false
- }
- }
- } catch (e: AssertionError) {
- Log.warn(e) { "Failed to get isPostviewSupported from Camera-$camera" }
+ lazyOrFalse({ "$camera#isPostviewSupported" }) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ Api34Compat.isPostviewAvailable(extensionCharacteristics, cameraExtension)
+ } else {
+ false
+ }
+ }
+
+ private val _isCaptureProgressSupported: Lazy<Boolean> =
+ lazyOrFalse({ "$camera#isCaptureProgressSupported" }) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ Api34Compat.isCaptureProcessProgressAvailable(
+ extensionCharacteristics,
+ cameraExtension
+ )
+ } else {
false
}
}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraMetadata.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraMetadata.kt
index 5c82c66..eef6f5a 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraMetadata.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraMetadata.kt
@@ -17,7 +17,6 @@
package androidx.camera.camera2.pipe.compat
import android.hardware.camera2.CameraCharacteristics
-import android.hardware.camera2.CameraExtensionCharacteristics
import android.hardware.camera2.CaptureRequest
import android.hardware.camera2.CaptureResult
import android.os.Build
@@ -130,10 +129,6 @@
return metadataProvider.awaitCameraMetadata(cameraId)
}
- private fun getExtensionCharacteristics(): CameraExtensionCharacteristics {
- return metadataProvider.getCameraExtensionCharacteristics(camera)
- }
-
override suspend fun getExtensionMetadata(extension: Int): CameraExtensionMetadata {
val existing = synchronized(extensionCache) { extensionCache[extension] }
return if (existing != null) {
@@ -160,12 +155,7 @@
lazy(LazyThreadSafetyMode.PUBLICATION) {
try {
Debug.trace("Camera-$camera#supportedExtensions") {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- val extensionCharacteristics = getExtensionCharacteristics()
- Api31Compat.getSupportedExtensions(extensionCharacteristics).toSet()
- } else {
- emptySet()
- }
+ metadataProvider.getSupportedCameraExtensions(camera)
}
} catch (e: AssertionError) {
Log.warn(e) { "Failed to getSupportedExtensions from Camera-$camera" }
@@ -176,7 +166,10 @@
private val _keys: Lazy<Set<CameraCharacteristics.Key<*>>> =
lazy(LazyThreadSafetyMode.PUBLICATION) {
try {
- Debug.trace("$camera#keys") { characteristics.keys.orEmpty().toSet() }
+ Debug.trace("$camera#keys") {
+ @Suppress("UselessCallOnNotNull") // Untrusted API
+ characteristics.keys.orEmpty().toSet()
+ }
} catch (e: AssertionError) {
Log.warn(e) { "Failed to getKeys from $camera}" }
emptySet()
@@ -187,6 +180,7 @@
lazy(LazyThreadSafetyMode.PUBLICATION) {
try {
Debug.trace("$camera#availableCaptureRequestKeys") {
+ @Suppress("UselessCallOnNotNull") // Untrusted API
characteristics.availableCaptureRequestKeys.orEmpty().toSet()
}
} catch (e: AssertionError) {
@@ -199,6 +193,7 @@
lazy(LazyThreadSafetyMode.PUBLICATION) {
try {
Debug.trace("$camera#availableCaptureResultKeys") {
+ @Suppress("UselessCallOnNotNull") // Untrusted API
characteristics.availableCaptureResultKeys.orEmpty().toSet()
}
} catch (e: AssertionError) {
@@ -271,7 +266,7 @@
return this.get(key)
} catch (exception: AssertionError) {
throw IllegalStateException(
- "Failed to get characteristic for $key: " + "Framework throw an AssertionError"
+ "Failed to get characteristic for $key: Framework throw an AssertionError"
)
}
}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2MetadataCache.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2MetadataCache.kt
index d32fad1..3ee3ee4 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2MetadataCache.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2MetadataCache.kt
@@ -138,6 +138,14 @@
}
}
+ override fun getSupportedCameraExtensions(cameraId: CameraId): Set<Int> {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ val extensionCharacteristics = getCameraExtensionCharacteristics(cameraId)
+ return Api31Compat.getSupportedExtensions(extensionCharacteristics).toSet()
+ }
+ return emptySet()
+ }
+
private fun createCameraMetadata(cameraId: CameraId, redacted: Boolean): Camera2CameraMetadata {
val start = Timestamps.now(timeSource)
@@ -240,7 +248,7 @@
return@trace extensionMetadata
} catch (throwable: Throwable) {
throw IllegalStateException(
- "Failed to load extension metadata " + "for $cameraId!",
+ "Failed to load extension metadata for $cameraId!",
throwable
)
}
@@ -248,7 +256,7 @@
}
@RequiresApi(Build.VERSION_CODES.S)
- override fun getCameraExtensionCharacteristics(
+ private fun getCameraExtensionCharacteristics(
cameraId: CameraId
): CameraExtensionCharacteristics {
synchronized(extensionCharacteristicsCache) {
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2MetadataProvider.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2MetadataProvider.kt
index 9ebad5a..0968c3c 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2MetadataProvider.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2MetadataProvider.kt
@@ -16,13 +16,13 @@
package androidx.camera.camera2.pipe.compat
-import android.hardware.camera2.CameraExtensionCharacteristics
import androidx.camera.camera2.pipe.CameraExtensionMetadata
import androidx.camera.camera2.pipe.CameraId
import androidx.camera.camera2.pipe.CameraMetadata
/** Interface that can be used to query for [CameraMetadata] using an existing [CameraId]. */
internal interface Camera2MetadataProvider {
+
/** Attempt to retrieve [CameraMetadata], suspending the caller if it is not yet available. */
suspend fun getCameraMetadata(cameraId: CameraId): CameraMetadata
@@ -31,9 +31,6 @@
*/
fun awaitCameraMetadata(cameraId: CameraId): CameraMetadata
- /** Attempt to retrieve [CameraExtensionCharacteristics] */
- fun getCameraExtensionCharacteristics(cameraId: CameraId): CameraExtensionCharacteristics
-
/**
* Attempt to retrieve [CameraExtensionMetadata], blocking the calling thread if it is not yet
* available.
@@ -48,4 +45,7 @@
* available.
*/
fun awaitCameraExtensionMetadata(cameraId: CameraId, extension: Int): CameraExtensionMetadata
+
+ /** Retrieve the set of supported Camera2 Extensions for the given camera. */
+ fun getSupportedCameraExtensions(cameraId: CameraId): Set<Int>
}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExtensionSessionState.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExtensionSessionState.kt
index b44a7cb..6865b04 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExtensionSessionState.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExtensionSessionState.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:RequiresApi(31) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-
package androidx.camera.camera2.pipe.compat
import android.hardware.camera2.CameraCaptureSession
@@ -34,6 +32,7 @@
* @param captureSessionState The [CaptureSessionState] instance to delegate the callback methods
* to.
*/
+@RequiresApi(31)
internal class ExtensionSessionState(private val captureSessionState: CaptureSessionState) :
CameraExtensionSessionWrapper.StateCallback {
override fun onConfigured(session: CameraExtensionSessionWrapper) {
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExtensionSessionWrapper.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExtensionSessionWrapper.kt
index f3bc8756..0c86a32 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExtensionSessionWrapper.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExtensionSessionWrapper.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:RequiresApi(31) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-
package androidx.camera.camera2.pipe.compat
import android.hardware.camera2.CameraCaptureSession
@@ -67,7 +65,7 @@
}
}
-@RequiresApi(31) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@RequiresApi(31)
internal class AndroidExtensionSessionStateCallback(
private val device: CameraDeviceWrapper,
private val stateCallback: CameraExtensionSessionWrapper.StateCallback,
@@ -137,7 +135,7 @@
}
}
-@RequiresApi(31) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@RequiresApi(31)
internal open class AndroidCameraExtensionSession(
override val device: CameraDeviceWrapper,
private val cameraExtensionSession: CameraExtensionSession,
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
index 09dbcec..4035977 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-// TODO(b/200306659): Remove and replace with annotation on package-info.java
@file:Suppress("DEPRECATION")
package androidx.camera.camera2.pipe.config
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/core/Debug.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/core/Debug.kt
index 545cacb..a7471b8 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/core/Debug.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/core/Debug.kt
@@ -44,7 +44,7 @@
* @param label A name of the code section to appear in the trace.
* @param block A block of code which is being traced.
*/
- inline fun <T> trace(label: String, crossinline block: () -> T): T {
+ inline fun <T> trace(label: String, block: () -> T): T {
try {
traceStart { label }
return block()
@@ -54,7 +54,7 @@
}
/** Wrap the specified [block] in a trace and timing calls. */
- internal inline fun <T> instrument(label: String, crossinline block: () -> T): T {
+ internal inline fun <T> instrument(label: String, block: () -> T): T {
val start = systemTimeSource.now()
try {
traceStart { label }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/core/Lazy.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/core/Lazy.kt
new file mode 100644
index 0000000..6de6a8d
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/core/Lazy.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe.core
+
+/**
+ * Utility function for creating inline [Lazy] instances that default to false if the block throws
+ * an exception while trying to read or compute the value.
+ */
+internal inline fun lazyOrFalse(
+ crossinline blockNameFn: () -> String,
+ crossinline block: () -> Boolean
+): Lazy<Boolean> =
+ lazy(LazyThreadSafetyMode.PUBLICATION) {
+ val blockName = blockNameFn()
+ try {
+ Debug.trace(blockName) { block() }
+ } catch (e: Throwable) {
+ Log.warn(e) { "Failed to get $blockName! Caching false and ignoring exception." }
+ false
+ }
+ }
+
+internal inline fun lazyOrFalse(
+ blockName: String,
+ crossinline block: () -> Boolean
+): Lazy<Boolean> = lazyOrFalse({ blockName }, block)
+
+/**
+ * Utility function for creating [Lazy] instances that default to an empty set if the block throws
+ * an exception while trying to read or compute the value.
+ */
+internal inline fun <T> lazyOrEmptySet(
+ crossinline blockNameFn: () -> String,
+ crossinline block: () -> Set<T>?
+): Lazy<Set<T>> =
+ lazy(LazyThreadSafetyMode.PUBLICATION) {
+ val blockName = blockNameFn()
+ try {
+ Debug.trace(blockName) { block() ?: emptySet() }
+ } catch (e: Throwable) {
+ Log.warn(e) { "Failed to get $blockName! Caching {} and ignoring exception." }
+ emptySet()
+ }
+ }
+
+internal inline fun <T> lazyOrEmptySet(
+ blockName: String,
+ crossinline block: () -> Set<T>?
+): Lazy<Set<T>> = lazyOrEmptySet({ blockName }, block)
+
+/**
+ * Utility function for creating [Lazy] instances that default to an empty list if the block throws
+ * an exception while trying to read or compute the value.
+ */
+internal inline fun <T> lazyOrEmptyList(
+ crossinline blockNameFn: () -> String,
+ crossinline block: () -> List<T>?
+): Lazy<List<T>> =
+ lazy(LazyThreadSafetyMode.PUBLICATION) {
+ val blockName = blockNameFn()
+ try {
+ Debug.trace(blockName) { block() ?: emptyList() }
+ } catch (e: Throwable) {
+ Log.warn(e) { "Failed to get $blockName! Caching [] and ignoring exception." }
+ emptyList()
+ }
+ }
+
+internal inline fun <T> lazyOrEmptyList(
+ blockName: String,
+ crossinline block: () -> List<T>
+): Lazy<List<T>> = lazyOrEmptyList({ blockName }, block)
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt
index eceb3d8..70cf322 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt
@@ -18,7 +18,6 @@
import android.content.Context
import android.graphics.SurfaceTexture
-import android.hardware.camera2.CameraExtensionCharacteristics
import android.os.Build
import android.os.Looper
import android.util.Size
@@ -55,7 +54,6 @@
import dagger.Module
import dagger.Provides
import javax.inject.Singleton
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Test
@@ -66,7 +64,6 @@
@RunWith(RobolectricCameraPipeTestRunner::class)
@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
-@OptIn(ExperimentalCoroutinesApi::class)
internal class CaptureSessionFactoryTest {
private val context = ApplicationProvider.getApplicationContext() as Context
private val mainLooper = Shadows.shadowOf(Looper.getMainLooper())
@@ -212,24 +209,22 @@
return fakeCamera.metadata
}
- override fun getCameraExtensionCharacteristics(
- cameraId: CameraId
- ): CameraExtensionCharacteristics {
- TODO("b/299356087 - Add support for fake extension metadata")
- }
-
override suspend fun getCameraExtensionMetadata(
cameraId: CameraId,
extension: Int
): CameraExtensionMetadata {
- TODO("b/299356087 - Add support for fake extension metadata")
+ throw UnsupportedOperationException("Unused for internal tests")
}
override fun awaitCameraExtensionMetadata(
cameraId: CameraId,
extension: Int
): CameraExtensionMetadata {
- TODO("b/299356087 - Add support for fake extension metadata")
+ throw UnsupportedOperationException("Unused for internal tests")
+ }
+
+ override fun getSupportedCameraExtensions(cameraId: CameraId): Set<Int> {
+ throw UnsupportedOperationException("Unused for internal tests")
}
}
}
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/RetryingCameraStateOpenerTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/RetryingCameraStateOpenerTest.kt
index 7ce7123..dce35b4 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/RetryingCameraStateOpenerTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/RetryingCameraStateOpenerTest.kt
@@ -18,7 +18,6 @@
import android.hardware.camera2.CameraAccessException
import android.hardware.camera2.CameraDevice
-import android.hardware.camera2.CameraExtensionCharacteristics
import android.os.Build
import androidx.camera.camera2.pipe.CameraError
import androidx.camera.camera2.pipe.CameraError.Companion.ERROR_CAMERA_DISABLED
@@ -70,24 +69,22 @@
override fun awaitCameraMetadata(cameraId: CameraId): CameraMetadata =
FakeCameraMetadata(cameraId = cameraId)
- override fun getCameraExtensionCharacteristics(
- cameraId: CameraId
- ): CameraExtensionCharacteristics {
- TODO("b/299356087 - Add support for fake extension metadata")
- }
-
override suspend fun getCameraExtensionMetadata(
cameraId: CameraId,
extension: Int
): CameraExtensionMetadata {
- TODO("b/299356087 - Add support for fake extension metadata")
+ throw UnsupportedOperationException("Not supported for this test")
}
override fun awaitCameraExtensionMetadata(
cameraId: CameraId,
extension: Int
): CameraExtensionMetadata {
- TODO("b/299356087 - Add support for fake extension metadata")
+ throw UnsupportedOperationException("Not supported for this test")
+ }
+
+ override fun getSupportedCameraExtensions(cameraId: CameraId): Set<Int> {
+ throw UnsupportedOperationException("Not supported for this test")
}
}
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraMetadataProvider.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCamera2MetadataProvider.kt
similarity index 72%
rename from camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraMetadataProvider.kt
rename to camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCamera2MetadataProvider.kt
index 900c91c..f5dc394 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraMetadataProvider.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCamera2MetadataProvider.kt
@@ -16,16 +16,14 @@
package androidx.camera.camera2.pipe.testing
-import android.hardware.camera2.CameraExtensionCharacteristics
import androidx.camera.camera2.pipe.CameraExtensionMetadata
import androidx.camera.camera2.pipe.CameraId
import androidx.camera.camera2.pipe.CameraMetadata
import androidx.camera.camera2.pipe.compat.Camera2MetadataProvider
/** Utility class for providing fake metadata for tests. */
-class FakeCameraMetadataProvider(
- private val fakeMetadata: Map<CameraId, CameraMetadata> = emptyMap(),
- private val fakeExtensionMetadata: Map<CameraId, CameraExtensionMetadata> = emptyMap()
+class FakeCamera2MetadataProvider(
+ private val fakeMetadata: Map<CameraId, CameraMetadata> = emptyMap()
) : Camera2MetadataProvider {
override suspend fun getCameraMetadata(cameraId: CameraId): CameraMetadata =
awaitCameraMetadata(cameraId)
@@ -35,12 +33,6 @@
"Failed to find metadata for $cameraId. Available fakeMetadata is $fakeMetadata"
}
- override fun getCameraExtensionCharacteristics(
- cameraId: CameraId
- ): CameraExtensionCharacteristics {
- TODO("b/299356087 - Add support for fake extension metadata")
- }
-
override suspend fun getCameraExtensionMetadata(
cameraId: CameraId,
extension: Int
@@ -49,9 +41,8 @@
override fun awaitCameraExtensionMetadata(
cameraId: CameraId,
extension: Int
- ): CameraExtensionMetadata =
- checkNotNull(fakeExtensionMetadata[cameraId]) {
- "Failed to find extension metadata for $cameraId. Available " +
- "fakeExtensionMetadata is $fakeExtensionMetadata"
- }
+ ): CameraExtensionMetadata = awaitCameraMetadata(cameraId).awaitExtensionMetadata(extension)
+
+ override fun getSupportedCameraExtensions(cameraId: CameraId): Set<Int> =
+ awaitCameraMetadata(cameraId).supportedExtensions
}
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/RobolectricCameras.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/RobolectricCameras.kt
index 65a5440..de2ec07 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/RobolectricCameras.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/RobolectricCameras.kt
@@ -32,7 +32,7 @@
import androidx.camera.camera2.pipe.CameraMetadata
import androidx.camera.camera2.pipe.compat.Camera2CameraMetadata
import androidx.test.core.app.ApplicationProvider
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import kotlinx.atomicfu.atomic
import org.junit.After
import org.junit.Test
@@ -104,7 +104,7 @@
cameraId,
false,
characteristics,
- FakeCameraMetadataProvider(),
+ FakeCamera2MetadataProvider(),
emptyMap(),
emptySet()
)
@@ -164,7 +164,6 @@
@RunWith(RobolectricCameraPipeTestRunner::class)
@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
class RobolectricCamerasTest {
- private val context = ApplicationProvider.getApplicationContext() as Context
private val mainLooper = shadowOf(Looper.getMainLooper())
@Test
@@ -175,13 +174,13 @@
)
val fakeCamera = RobolectricCameras.open(fakeCameraId)
- Truth.assertThat(fakeCamera).isNotNull()
- Truth.assertThat(fakeCamera.cameraId).isEqualTo(fakeCameraId)
- Truth.assertThat(fakeCamera.cameraDevice).isNotNull()
- Truth.assertThat(fakeCamera.characteristics).isNotNull()
- Truth.assertThat(fakeCamera.characteristics[CameraCharacteristics.LENS_FACING]).isNotNull()
- Truth.assertThat(fakeCamera.metadata).isNotNull()
- Truth.assertThat(fakeCamera.metadata[CameraCharacteristics.LENS_FACING]).isNotNull()
+ assertThat(fakeCamera).isNotNull()
+ assertThat(fakeCamera.cameraId).isEqualTo(fakeCameraId)
+ assertThat(fakeCamera.cameraDevice).isNotNull()
+ assertThat(fakeCamera.characteristics).isNotNull()
+ assertThat(fakeCamera.characteristics[CameraCharacteristics.LENS_FACING]).isNotNull()
+ assertThat(fakeCamera.metadata).isNotNull()
+ assertThat(fakeCamera.metadata[CameraCharacteristics.LENS_FACING]).isNotNull()
}
@After