Aperture: Extract overlay configuration into a new class
Change-Id: Ie6f158eb8ef2657b18bc26ce87ed89f94238225c
diff --git a/app/src/main/java/org/lineageos/aperture/CameraActivity.kt b/app/src/main/java/org/lineageos/aperture/CameraActivity.kt
index 7f1cfe4..bc22892 100644
--- a/app/src/main/java/org/lineageos/aperture/CameraActivity.kt
+++ b/app/src/main/java/org/lineageos/aperture/CameraActivity.kt
@@ -1524,7 +1524,7 @@
)
)
.setAllowedResolutionMode(
- if (cameraManager.enableHighResolution) {
+ if (cameraManager.overlayConfiguration.enableHighResolution) {
ResolutionSelector.PREFER_HIGHER_RESOLUTION_OVER_CAPTURE_RATE
} else {
ResolutionSelector.PREFER_CAPTURE_RATE_OVER_HIGHER_RESOLUTION
diff --git a/app/src/main/java/org/lineageos/aperture/camera/CameraManager.kt b/app/src/main/java/org/lineageos/aperture/camera/CameraManager.kt
index f07db70..e71f284 100644
--- a/app/src/main/java/org/lineageos/aperture/camera/CameraManager.kt
+++ b/app/src/main/java/org/lineageos/aperture/camera/CameraManager.kt
@@ -10,15 +10,12 @@
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.video.Quality
import androidx.camera.view.LifecycleCameraController
-import org.lineageos.aperture.R
-import org.lineageos.aperture.ext.*
import org.lineageos.aperture.models.CameraFacing
import org.lineageos.aperture.models.CameraMode
import org.lineageos.aperture.models.CameraType
-import org.lineageos.aperture.models.FrameRate
+import org.lineageos.aperture.utils.OverlayConfiguration
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
-import kotlin.math.absoluteValue
/**
* Class managing an app camera session
@@ -31,80 +28,7 @@
val cameraController = LifecycleCameraController(context)
val cameraExecutor: ExecutorService = Executors.newSingleThreadExecutor()
- private val additionalVideoConfigurations by lazy {
- mutableMapOf<String, MutableMap<Quality, MutableMap<FrameRate, Boolean>>>().apply {
- context.resources.getStringArray(context, R.array.config_additionalVideoConfigurations)
- .let {
- if (it.size % 3 != 0) {
- // Invalid configuration
- return@apply
- }
-
- for (i in it.indices step 3) {
- val cameraId = it[i]
- val frameRates = it[i + 2].split("|").mapNotNull { frameRate ->
- FrameRate.fromValue(frameRate.toInt().absoluteValue)?.let { value ->
- value to frameRate.startsWith('-')
- }
- }.toMap()
-
- it[i + 1].split("|").mapNotNull { quality ->
- when (quality) {
- "sd" -> Quality.SD
- "hd" -> Quality.HD
- "fhd" -> Quality.FHD
- "uhd" -> Quality.UHD
- else -> null
- }
- }.distinct().forEach { quality ->
- getOrCreate(cameraId).apply {
- getOrCreate(quality).apply {
- putAll(frameRates)
- }
- }
- }
- }
- }
- }.map { a ->
- a.key to a.value.map { b ->
- b.key to b.value.toList()
- }.toMap()
- }.toMap()
- }
- private val enableAuxCameras by lazy {
- context.resources.getBoolean(context, R.bool.config_enableAuxCameras)
- }
- private val ignoredAuxCameraIds by lazy {
- context.resources.getStringArray(context, R.array.config_ignoredAuxCameraIds)
- }
- private val ignoreLogicalAuxCameras by lazy {
- context.resources.getBoolean(context, R.bool.config_ignoreLogicalAuxCameras)
- }
- private val logicalZoomRatios by lazy {
- mutableMapOf<String, MutableMap<Float, Float>>().apply {
- context.resources.getStringArray(context, R.array.config_logicalZoomRatios).let {
- if (it.size % 3 != 0) {
- // Invalid configuration
- return@apply
- }
-
- for (i in it.indices step 3) {
- val cameraId = it[i]
- val approximateZoomRatio = it[i + 1].toFloat()
- val exactZoomRatio = it[i + 2].toFloat()
-
- getOrCreate(cameraId).apply {
- this[approximateZoomRatio] = exactZoomRatio
- }
- }
- }
- }.map { a ->
- a.key to a.value.toMap()
- }.toMap()
- }
- val enableHighResolution by lazy {
- context.resources.getBoolean(context, R.bool.config_enableHighResolution)
- }
+ val overlayConfiguration = OverlayConfiguration(context)
private val cameras: List<Camera>
get() = cameraProvider.availableCameraInfos.map {
@@ -113,7 +37,8 @@
// We expect device cameras to never change
private val internalCameras = cameras.filter {
- it.cameraType == CameraType.INTERNAL && !ignoredAuxCameraIds.contains(it.cameraId)
+ it.cameraType == CameraType.INTERNAL
+ && !overlayConfiguration.ignoredAuxCameraIds.contains(it.cameraId)
}
private val backCameras = prepareDeviceCamerasList(CameraFacing.BACK)
@@ -151,10 +76,10 @@
get() = availableCameras.filter { it.supportsVideoRecording }
fun getAdditionalVideoFrameRates(cameraId: String, quality: Quality) =
- additionalVideoConfigurations[cameraId]?.get(quality) ?: setOf()
+ overlayConfiguration.additionalVideoConfigurations[cameraId]?.get(quality) ?: setOf()
fun getLogicalZoomRatios(cameraId: String) = mutableMapOf(1.0f to 1.0f).apply {
- logicalZoomRatios[cameraId]?.let {
+ overlayConfiguration.logicalZoomRatios[cameraId]?.let {
putAll(it)
}
}.toSortedMap()
@@ -253,7 +178,7 @@
val mainCamera = facingCameras.first()
- if (!enableAuxCameras) {
+ if (!overlayConfiguration.enableAuxCameras) {
// Return only the main camera
return listOf(mainCamera)
}
@@ -261,7 +186,7 @@
// Get the list of aux cameras
val auxCameras = facingCameras
.drop(1)
- .filter { !ignoreLogicalAuxCameras || !it.isLogical }
+ .filter { !overlayConfiguration.ignoreLogicalAuxCameras || !it.isLogical }
return listOf(mainCamera) + auxCameras
}
diff --git a/app/src/main/java/org/lineageos/aperture/utils/OverlayConfiguration.kt b/app/src/main/java/org/lineageos/aperture/utils/OverlayConfiguration.kt
new file mode 100644
index 0000000..3ff4cf9
--- /dev/null
+++ b/app/src/main/java/org/lineageos/aperture/utils/OverlayConfiguration.kt
@@ -0,0 +1,111 @@
+/*
+ * SPDX-FileCopyrightText: 2024 The LineageOS Project
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.lineageos.aperture.utils
+
+import android.content.Context
+import androidx.camera.video.Quality
+import org.lineageos.aperture.R
+import org.lineageos.aperture.ext.getBoolean
+import org.lineageos.aperture.ext.getOrCreate
+import org.lineageos.aperture.ext.getStringArray
+import org.lineageos.aperture.models.FrameRate
+import kotlin.math.absoluteValue
+
+/**
+ * Overlay configuration manager.
+ */
+class OverlayConfiguration(context: Context) {
+ private val resources = context.resources
+
+ /**
+ * @see R.bool.config_enableAuxCameras
+ */
+ val enableAuxCameras = resources.getBoolean(context, R.bool.config_enableAuxCameras)
+
+ /**
+ * @see R.array.config_ignoredAuxCameraIds
+ */
+ val ignoredAuxCameraIds = resources.getStringArray(context, R.array.config_ignoredAuxCameraIds)
+
+ /**
+ * @see R.bool.config_ignoreLogicalAuxCameras
+ */
+ val ignoreLogicalAuxCameras = resources.getBoolean(
+ context, R.bool.config_ignoreLogicalAuxCameras
+ )
+
+ /**
+ * @see R.array.config_additionalVideoConfigurations
+ */
+ val additionalVideoConfigurations =
+ mutableMapOf<String, MutableMap<Quality, MutableMap<FrameRate, Boolean>>>().apply {
+ resources.getStringArray(context, R.array.config_additionalVideoConfigurations)
+ .let {
+ if (it.size % 3 != 0) {
+ // Invalid configuration
+ return@apply
+ }
+
+ for (i in it.indices step 3) {
+ val cameraId = it[i]
+ val frameRates = it[i + 2].split("|").mapNotNull { frameRate ->
+ FrameRate.fromValue(frameRate.toInt().absoluteValue)?.let { value ->
+ value to frameRate.startsWith('-')
+ }
+ }.toMap()
+
+ it[i + 1].split("|").mapNotNull { quality ->
+ when (quality) {
+ "sd" -> Quality.SD
+ "hd" -> Quality.HD
+ "fhd" -> Quality.FHD
+ "uhd" -> Quality.UHD
+ else -> null
+ }
+ }.distinct().forEach { quality ->
+ getOrCreate(cameraId).apply {
+ getOrCreate(quality).apply {
+ putAll(frameRates)
+ }
+ }
+ }
+ }
+ }
+ }.map { a ->
+ a.key to a.value.map { b ->
+ b.key to b.value.toList()
+ }.toMap()
+ }.toMap()
+
+ /**
+ * @see R.array.config_logicalZoomRatios
+ */
+ val logicalZoomRatios = mutableMapOf<String, MutableMap<Float, Float>>().apply {
+ resources.getStringArray(context, R.array.config_logicalZoomRatios).let {
+ if (it.size % 3 != 0) {
+ // Invalid configuration
+ return@apply
+ }
+
+ for (i in it.indices step 3) {
+ val cameraId = it[i]
+ val approximateZoomRatio = it[i + 1].toFloat()
+ val exactZoomRatio = it[i + 2].toFloat()
+
+ getOrCreate(cameraId).apply {
+ this[approximateZoomRatio] = exactZoomRatio
+ }
+ }
+ }
+ }.map { a ->
+ a.key to a.value.toMap()
+ }.toMap()
+
+ /**
+ * @see R.bool.config_enableHighResolution
+ */
+ val enableHighResolution = resources.getBoolean(context, R.bool.config_enableHighResolution)
+}