diff --git a/core/model/build.gradle.kts b/core/model/build.gradle.kts index 866fb0cc9..abf84fe8f 100644 --- a/core/model/build.gradle.kts +++ b/core/model/build.gradle.kts @@ -17,7 +17,6 @@ plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.kapt) - alias(libs.plugins.google.protobuf) } android { @@ -72,35 +71,12 @@ dependencies { // proto datastore implementation(libs.androidx.datastore) - implementation(libs.protobuf.kotlin.lite) // Testing testImplementation(libs.junit) testImplementation(libs.truth) } -protobuf { - protoc { - artifact = "com.google.protobuf:protoc:3.21.12" - } - - generateProtoTasks { - all().forEach { task -> - task.builtins { - create("java") { - option("lite") - } - } - - task.builtins { - create("kotlin") { - option("lite") - } - } - } - } -} - // Allow references to generated code kapt { correctErrorTypes = true diff --git a/core/model/src/main/java/com/google/jetpackcamera/model/AspectRatio.kt b/core/model/src/main/java/com/google/jetpackcamera/model/AspectRatio.kt index 8dafa4a5f..8b96e1304 100644 --- a/core/model/src/main/java/com/google/jetpackcamera/model/AspectRatio.kt +++ b/core/model/src/main/java/com/google/jetpackcamera/model/AspectRatio.kt @@ -15,8 +15,6 @@ */ package com.google.jetpackcamera.model -import com.google.jetpackcamera.model.proto.AspectRatio as AspectRatioProto - enum class AspectRatio(val numerator: Int, val denominator: Int) { THREE_FOUR(3, 4), NINE_SIXTEEN(9, 16), @@ -31,21 +29,4 @@ enum class AspectRatio(val numerator: Int, val denominator: Int) { * Returns the landscape aspect ratio as a [Float]. */ fun toLandscapeFloat(): Float = denominator.toFloat() / numerator - - companion object { - - /** returns the AspectRatio enum equivalent of a provided AspectRatioProto */ - fun fromProto(aspectRatioProto: AspectRatioProto): AspectRatio { - return when (aspectRatioProto) { - AspectRatioProto.ASPECT_RATIO_NINE_SIXTEEN -> NINE_SIXTEEN - AspectRatioProto.ASPECT_RATIO_ONE_ONE -> ONE_ONE - - // defaults to 3:4 aspect ratio - AspectRatioProto.ASPECT_RATIO_THREE_FOUR, - AspectRatioProto.ASPECT_RATIO_UNDEFINED, - AspectRatioProto.UNRECOGNIZED - -> THREE_FOUR - } - } - } } diff --git a/core/model/src/main/java/com/google/jetpackcamera/model/DebugSettings.kt b/core/model/src/main/java/com/google/jetpackcamera/model/DebugSettings.kt index 25e05698e..e5bbf6751 100644 --- a/core/model/src/main/java/com/google/jetpackcamera/model/DebugSettings.kt +++ b/core/model/src/main/java/com/google/jetpackcamera/model/DebugSettings.kt @@ -15,12 +15,6 @@ */ package com.google.jetpackcamera.model -import android.util.Base64 -import com.google.jetpackcamera.model.LensFacing.Companion.toProto -import com.google.jetpackcamera.model.TestPattern.Companion.toProto -import com.google.jetpackcamera.model.proto.DebugSettings as DebugSettingsProto -import com.google.jetpackcamera.model.proto.debugSettings as debugSettingsProto - /** * Data class for defining settings used in debug flows within the app. * @@ -38,64 +32,81 @@ data class DebugSettings( ) { companion object { /** - * Creates a [DebugSettings] domain model from its protobuf representation. - * - * @param proto The [DebugSettingsProto] instance. - * @return The corresponding [DebugSettings] instance. + * Parses the string into a [DebugSettings] instance. */ - fun fromProto(proto: DebugSettingsProto): DebugSettings { - return DebugSettings( - isDebugModeEnabled = proto.isDebugModeEnabled, - singleLensMode = if (proto.hasSingleLensMode()) { - LensFacing.fromProto(proto.singleLensMode) - } else { - null - }, - testPattern = TestPattern.fromProto(proto.testPattern) - ) - } + fun parseFromString(value: String): DebugSettings { + val parts = value.split(";") + var isDebugModeEnabled = false + var singleLensMode: LensFacing? = null + var testPattern: TestPattern = TestPattern.Off - /** - * Converts a [DebugSettings] domain model to its protobuf representation. - * - * @receiver The [DebugSettings] instance to convert. - * @return The corresponding [DebugSettingsProto] instance. - */ - fun DebugSettings.toProto(): DebugSettingsProto = debugSettingsProto { - isDebugModeEnabled = this@toProto.isDebugModeEnabled - this@toProto.singleLensMode?.let { lensFacing -> - singleLensMode = lensFacing.toProto() + for (part in parts) { + val kv = part.split(":") + if (kv.size == 2) { + when (kv[0]) { + "debug" -> isDebugModeEnabled = kv[1].toBoolean() + "lens" -> singleLensMode = enumValues() + .firstOrNull { it.name == kv[1] } + "pattern" -> { + testPattern = when (kv[1]) { + "Off" -> TestPattern.Off + "ColorBars" -> TestPattern.ColorBars + "ColorBarsFadeToGray" -> TestPattern.ColorBarsFadeToGray + "PN9" -> TestPattern.PN9 + "Custom1" -> TestPattern.Custom1 + else -> { + if (kv[1].startsWith("SolidColor(") && + kv[1].endsWith(")") + ) { + val channels = kv[1] + .removePrefix("SolidColor(") + .removeSuffix(")") + .split(",") + if (channels.size == 4) { + val red = channels[0].toUIntOrNull() + val greenEven = channels[1].toUIntOrNull() + val greenOdd = channels[2].toUIntOrNull() + val blue = channels[3].toUIntOrNull() + if (red != null && + greenEven != null && + greenOdd != null && + blue != null + ) { + TestPattern.SolidColor( + red, + greenEven, + greenOdd, + blue + ) + } else { + TestPattern.Off + } + } else { + TestPattern.Off + } + } else { + TestPattern.Off + } + } + } + } + } + } } - testPattern = this@toProto.testPattern.toProto() - } - - /** - * Parses the encoded byte array into a [DebugSettings] instance. - */ - fun parseFromByteArray(value: ByteArray): DebugSettings { - val protoValue = DebugSettingsProto.parseFrom(value) - return fromProto(protoValue) + return DebugSettings(isDebugModeEnabled, singleLensMode, testPattern) } /** - * Parses the Base64 encoded string into a [DebugSettings] instance. - */ - fun parseFromString(value: String): DebugSettings { - val decodedBytes = Base64.decode(value, Base64.NO_WRAP) - return parseFromByteArray(decodedBytes) - } - - /** - * Encodes the [DebugSettings] data class into a byte array. - */ - fun DebugSettings.encodeAsByteArray(): ByteArray = this.toProto().toByteArray() - - /** - * Encodes the [DebugSettings] data class to a Base64 string. + * Encodes the [DebugSettings] data class to a string. */ fun DebugSettings.encodeAsString(): String { - val protoValue = this.toProto() // Data class -> Proto - return Base64.encodeToString(protoValue.toByteArray(), Base64.NO_WRAP) + val lensStr = singleLensMode?.name ?: "" + val patternStr = when (val pattern = testPattern) { + is TestPattern.SolidColor -> + "SolidColor(${pattern.red},${pattern.greenEven},${pattern.greenOdd},${pattern.blue})" + else -> pattern.toString() + } + return "debug:$isDebugModeEnabled;lens:$lensStr;pattern:$patternStr" } } } diff --git a/core/model/src/main/java/com/google/jetpackcamera/model/DynamicRange.kt b/core/model/src/main/java/com/google/jetpackcamera/model/DynamicRange.kt index ecc228741..391d8cb36 100644 --- a/core/model/src/main/java/com/google/jetpackcamera/model/DynamicRange.kt +++ b/core/model/src/main/java/com/google/jetpackcamera/model/DynamicRange.kt @@ -14,33 +14,9 @@ * limitations under the License. */ package com.google.jetpackcamera.model -import com.google.jetpackcamera.model.proto.DynamicRange as DynamicRangeProto - val DEFAULT_HDR_DYNAMIC_RANGE = DynamicRange.HLG10 enum class DynamicRange { SDR, - HLG10; - - companion object { - - /** returns the DynamicRangeType enum equivalent of a provided DynamicRangeTypeProto */ - fun fromProto(dynamicRangeProto: DynamicRangeProto): DynamicRange { - return when (dynamicRangeProto) { - DynamicRangeProto.DYNAMIC_RANGE_HLG10 -> HLG10 - - // Treat unrecognized and unspecified as SDR as a fallback - DynamicRangeProto.DYNAMIC_RANGE_SDR, - DynamicRangeProto.DYNAMIC_RANGE_UNSPECIFIED, - DynamicRangeProto.UNRECOGNIZED -> SDR - } - } - - fun DynamicRange.toProto(): DynamicRangeProto { - return when (this) { - SDR -> DynamicRangeProto.DYNAMIC_RANGE_SDR - HLG10 -> DynamicRangeProto.DYNAMIC_RANGE_HLG10 - } - } - } + HLG10 } diff --git a/core/model/src/main/java/com/google/jetpackcamera/model/ImageOutputFormat.kt b/core/model/src/main/java/com/google/jetpackcamera/model/ImageOutputFormat.kt index 8fa219ab8..c19a4826e 100644 --- a/core/model/src/main/java/com/google/jetpackcamera/model/ImageOutputFormat.kt +++ b/core/model/src/main/java/com/google/jetpackcamera/model/ImageOutputFormat.kt @@ -15,32 +15,9 @@ */ package com.google.jetpackcamera.model -import com.google.jetpackcamera.model.proto.ImageOutputFormat as ImageOutputFormatProto - val DEFAULT_HDR_IMAGE_OUTPUT = ImageOutputFormat.JPEG_ULTRA_HDR enum class ImageOutputFormat { JPEG, - JPEG_ULTRA_HDR; - - companion object { - - /** returns the DynamicRangeType enum equivalent of a provided DynamicRangeTypeProto */ - fun fromProto(imageOutputFormatProto: ImageOutputFormatProto): ImageOutputFormat { - return when (imageOutputFormatProto) { - ImageOutputFormatProto.IMAGE_OUTPUT_FORMAT_JPEG_ULTRA_HDR -> JPEG_ULTRA_HDR - - // Treat unrecognized as JPEG as a fallback - ImageOutputFormatProto.IMAGE_OUTPUT_FORMAT_JPEG, - ImageOutputFormatProto.UNRECOGNIZED -> JPEG - } - } - - fun ImageOutputFormat.toProto(): ImageOutputFormatProto { - return when (this) { - JPEG -> ImageOutputFormatProto.IMAGE_OUTPUT_FORMAT_JPEG - JPEG_ULTRA_HDR -> ImageOutputFormatProto.IMAGE_OUTPUT_FORMAT_JPEG_ULTRA_HDR - } - } - } + JPEG_ULTRA_HDR } diff --git a/core/model/src/main/java/com/google/jetpackcamera/model/LensFacing.kt b/core/model/src/main/java/com/google/jetpackcamera/model/LensFacing.kt index 4aa5a27b5..b72c807b0 100644 --- a/core/model/src/main/java/com/google/jetpackcamera/model/LensFacing.kt +++ b/core/model/src/main/java/com/google/jetpackcamera/model/LensFacing.kt @@ -15,8 +15,6 @@ */ package com.google.jetpackcamera.model -import com.google.jetpackcamera.model.proto.LensFacing as LensFacingProto - enum class LensFacing { BACK, FRONT; @@ -27,25 +25,4 @@ enum class LensFacing { BACK -> FRONT } } - - companion object { - - /** returns the LensFacing enum equivalent of a provided LensFacingProto */ - fun fromProto(lensFacingProto: LensFacingProto): LensFacing { - return when (lensFacingProto) { - LensFacingProto.LENS_FACING_BACK -> BACK - - // Treat unrecognized as front as a fallback - LensFacingProto.LENS_FACING_FRONT, - LensFacingProto.UNRECOGNIZED -> FRONT - } - } - - fun LensFacing.toProto(): LensFacingProto { - return when (this) { - BACK -> LensFacingProto.LENS_FACING_BACK - FRONT -> LensFacingProto.LENS_FACING_FRONT - } - } - } } diff --git a/core/model/src/main/java/com/google/jetpackcamera/model/LowLightBoostPriority.kt b/core/model/src/main/java/com/google/jetpackcamera/model/LowLightBoostPriority.kt index eb6aa7367..38da49b84 100644 --- a/core/model/src/main/java/com/google/jetpackcamera/model/LowLightBoostPriority.kt +++ b/core/model/src/main/java/com/google/jetpackcamera/model/LowLightBoostPriority.kt @@ -15,36 +15,7 @@ */ package com.google.jetpackcamera.model -import com.google.jetpackcamera.model.proto.LowLightBoostPriority as LowLightBoostPriorityProto - enum class LowLightBoostPriority { PRIORITIZE_AE_MODE, - PRIORITIZE_GOOGLE_PLAY_SERVICES; - - companion object { - /** - * Returns the [LowLightBoostPriority] enum equivalent of a provided [LowLightBoostPriorityProto]. - * - * @param lowLightBoostPriorityProto The proto to convert from. - * @return The converted [LowLightBoostPriority]. - */ - fun fromProto( - lowLightBoostPriorityProto: LowLightBoostPriorityProto - ): LowLightBoostPriority { - return when (lowLightBoostPriorityProto) { - LowLightBoostPriorityProto.LOW_LIGHT_BOOST_PRIORITY_AE_MODE -> PRIORITIZE_AE_MODE - LowLightBoostPriorityProto.LOW_LIGHT_BOOST_PRIORITY_GOOGLE_PLAY_SERVICES -> - PRIORITIZE_GOOGLE_PLAY_SERVICES - LowLightBoostPriorityProto.UNRECOGNIZED -> PRIORITIZE_AE_MODE // Default to AE mode - } - } - - fun LowLightBoostPriority.toProto(): LowLightBoostPriorityProto { - return when (this) { - PRIORITIZE_AE_MODE -> LowLightBoostPriorityProto.LOW_LIGHT_BOOST_PRIORITY_AE_MODE - PRIORITIZE_GOOGLE_PLAY_SERVICES -> - LowLightBoostPriorityProto.LOW_LIGHT_BOOST_PRIORITY_GOOGLE_PLAY_SERVICES - } - } - } + PRIORITIZE_GOOGLE_PLAY_SERVICES } diff --git a/core/model/src/main/java/com/google/jetpackcamera/model/StabilizationMode.kt b/core/model/src/main/java/com/google/jetpackcamera/model/StabilizationMode.kt index bf0dfbe1d..9c0a45422 100644 --- a/core/model/src/main/java/com/google/jetpackcamera/model/StabilizationMode.kt +++ b/core/model/src/main/java/com/google/jetpackcamera/model/StabilizationMode.kt @@ -15,9 +15,6 @@ */ package com.google.jetpackcamera.model -import com.google.jetpackcamera.model.proto.StabilizationMode as StabilizationModeProto - -/** Enum class representing the device's supported stabilization configurations. */ enum class StabilizationMode { /** Stabilization off */ OFF, @@ -36,22 +33,5 @@ enum class StabilizationMode { HIGH_QUALITY, /** Optical Stabilization (OIS) */ - OPTICAL; - - companion object { - /** returns the AspectRatio enum equivalent of a provided AspectRatioProto */ - fun fromProto(stabilizationModeProto: StabilizationModeProto): StabilizationMode = - when (stabilizationModeProto) { - StabilizationModeProto.STABILIZATION_MODE_OFF -> OFF - StabilizationModeProto.STABILIZATION_MODE_ON -> ON - StabilizationModeProto.STABILIZATION_MODE_HIGH_QUALITY -> HIGH_QUALITY - StabilizationModeProto.STABILIZATION_MODE_OPTICAL -> OPTICAL - - // Default to AUTO - StabilizationModeProto.STABILIZATION_MODE_UNDEFINED, - StabilizationModeProto.UNRECOGNIZED, - StabilizationModeProto.STABILIZATION_MODE_AUTO - -> AUTO - } - } + OPTICAL } diff --git a/core/model/src/main/java/com/google/jetpackcamera/model/TestPattern.kt b/core/model/src/main/java/com/google/jetpackcamera/model/TestPattern.kt index 15fc3e2f4..d758db1ee 100644 --- a/core/model/src/main/java/com/google/jetpackcamera/model/TestPattern.kt +++ b/core/model/src/main/java/com/google/jetpackcamera/model/TestPattern.kt @@ -15,16 +15,6 @@ */ package com.google.jetpackcamera.model -import com.google.jetpackcamera.model.proto.TestPattern as ProtoTestPattern -import com.google.jetpackcamera.model.proto.TestPattern.PatternCase -import com.google.jetpackcamera.model.proto.testPattern as protoTestPattern -import com.google.jetpackcamera.model.proto.testPatternColorBars -import com.google.jetpackcamera.model.proto.testPatternColorBarsFadeToGray -import com.google.jetpackcamera.model.proto.testPatternCustom1 -import com.google.jetpackcamera.model.proto.testPatternOff -import com.google.jetpackcamera.model.proto.testPatternPN9 -import com.google.jetpackcamera.model.proto.testPatternSolidColor - /** * Represents a test pattern to replace sensor pixel data. * @@ -179,56 +169,4 @@ sealed interface TestPattern { ) } } - - companion object { - /** - * Converts a [TestPattern] sealed interface instance to its Protocol Buffer representation - * ([ProtoTestPattern]). - */ - fun TestPattern.toProto(): ProtoTestPattern { - return protoTestPattern { - when (val pattern = this@toProto) { - is Off -> off = testPatternOff {} - is ColorBars -> colorBars = testPatternColorBars {} - is ColorBarsFadeToGray -> - colorBarsFadeToGray = testPatternColorBarsFadeToGray {} - is PN9 -> pn9 = testPatternPN9 {} - is Custom1 -> custom1 = testPatternCustom1 {} - is SolidColor -> solidColor = testPatternSolidColor { - red = pattern.red.toInt() - greenEven = pattern.greenEven.toInt() - greenOdd = pattern.greenOdd.toInt() - blue = pattern.blue.toInt() - } - } - } - } - - /** - * Converts a [ProtoTestPattern] Protocol Buffer message to its Kotlin [TestPattern] sealed - * interface representation. - */ - fun fromProto(proto: ProtoTestPattern): TestPattern { - return when (proto.patternCase) { - PatternCase.OFF, - PatternCase.PATTERN_NOT_SET -> { - // Default to Off if the oneof is not set - Off - } - PatternCase.COLOR_BARS -> ColorBars - PatternCase.COLOR_BARS_FADE_TO_GRAY -> ColorBarsFadeToGray - PatternCase.PN9 -> PN9 - PatternCase.CUSTOM1 -> Custom1 - PatternCase.SOLID_COLOR -> { - val protoSolidColor = proto.solidColor - SolidColor( - red = protoSolidColor.red.toUInt(), - greenEven = protoSolidColor.greenEven.toUInt(), - greenOdd = protoSolidColor.greenOdd.toUInt(), - blue = protoSolidColor.blue.toUInt() - ) - } - } - } - } } diff --git a/core/model/src/main/java/com/google/jetpackcamera/model/VideoQuality.kt b/core/model/src/main/java/com/google/jetpackcamera/model/VideoQuality.kt index 143b7d6a2..5c52aa61b 100644 --- a/core/model/src/main/java/com/google/jetpackcamera/model/VideoQuality.kt +++ b/core/model/src/main/java/com/google/jetpackcamera/model/VideoQuality.kt @@ -15,37 +15,10 @@ */ package com.google.jetpackcamera.model -import com.google.jetpackcamera.model.proto.VideoQuality as VideoQualityProto - enum class VideoQuality { UNSPECIFIED, SD, HD, FHD, - UHD; - - companion object { - /** returns the VideoQuality enum equivalent of a provided VideoQualityProto */ - fun fromProto(videoQualityProto: VideoQualityProto): VideoQuality { - return when (videoQualityProto) { - VideoQualityProto.VIDEO_QUALITY_SD -> SD - VideoQualityProto.VIDEO_QUALITY_HD -> HD - VideoQualityProto.VIDEO_QUALITY_FHD -> FHD - VideoQualityProto.VIDEO_QUALITY_UHD -> UHD - VideoQualityProto.VIDEO_QUALITY_UNSPECIFIED, - VideoQualityProto.UNRECOGNIZED - -> UNSPECIFIED - } - } - - fun VideoQuality.toProto(): VideoQualityProto { - return when (this) { - UNSPECIFIED -> VideoQualityProto.VIDEO_QUALITY_UNSPECIFIED - SD -> VideoQualityProto.VIDEO_QUALITY_SD - HD -> VideoQualityProto.VIDEO_QUALITY_HD - FHD -> VideoQualityProto.VIDEO_QUALITY_FHD - UHD -> VideoQualityProto.VIDEO_QUALITY_UHD - } - } - } + UHD } diff --git a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/aspect_ratio.proto b/core/model/src/main/proto/com/google/jetpackcamera/model/proto/aspect_ratio.proto deleted file mode 100644 index da8011c35..000000000 --- a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/aspect_ratio.proto +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2023 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. - */ - -syntax = "proto3"; - -option java_package = "com.google.jetpackcamera.model.proto"; -option java_multiple_files = true; - -enum AspectRatio { - ASPECT_RATIO_UNDEFINED = 0; - ASPECT_RATIO_THREE_FOUR = 1; - ASPECT_RATIO_NINE_SIXTEEN= 2; - ASPECT_RATIO_ONE_ONE = 3; -} \ No newline at end of file diff --git a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/dark_mode.proto b/core/model/src/main/proto/com/google/jetpackcamera/model/proto/dark_mode.proto deleted file mode 100644 index 8b38ef403..000000000 --- a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/dark_mode.proto +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2023 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. - */ - -syntax = "proto3"; - -option java_package = "com.google.jetpackcamera.model.proto"; -option java_multiple_files = true; - -enum DarkMode { - DARK_MODE_SYSTEM = 0; - DARK_MODE_LIGHT= 1; - DARK_MODE_DARK = 2; -} \ No newline at end of file diff --git a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/debug_settings.proto b/core/model/src/main/proto/com/google/jetpackcamera/model/proto/debug_settings.proto deleted file mode 100644 index 2c3633afc..000000000 --- a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/debug_settings.proto +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2025 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. - */ - -syntax = "proto3"; - -import "com/google/jetpackcamera/model/proto/lens_facing.proto"; -import "com/google/jetpackcamera/model/proto/test_pattern.proto"; - -option java_package = "com.google.jetpackcamera.model.proto"; -option java_multiple_files = true; - -message DebugSettings { - bool is_debug_mode_enabled = 1; - optional LensFacing single_lens_mode = 2; - TestPattern test_pattern = 3; -} diff --git a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/dynamic_range.proto b/core/model/src/main/proto/com/google/jetpackcamera/model/proto/dynamic_range.proto deleted file mode 100644 index 6ebe80b97..000000000 --- a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/dynamic_range.proto +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 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. - */ - -syntax = "proto3"; - -option java_package = "com.google.jetpackcamera.model.proto"; -option java_multiple_files = true; - -enum DynamicRange { - DYNAMIC_RANGE_UNSPECIFIED = 0; - DYNAMIC_RANGE_SDR = 1; - DYNAMIC_RANGE_HLG10 = 2; -} \ No newline at end of file diff --git a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/flash_mode.proto b/core/model/src/main/proto/com/google/jetpackcamera/model/proto/flash_mode.proto deleted file mode 100644 index fc87418e7..000000000 --- a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/flash_mode.proto +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2023 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. - */ - -syntax = "proto3"; - -option java_package = "com.google.jetpackcamera.model.proto"; -option java_multiple_files = true; - -enum FlashMode{ - FLASH_MODE_AUTO = 0; - FLASH_MODE_ON = 1; - FLASH_MODE_OFF = 2; - FLASH_MODE_LOW_LIGHT_BOOST = 3; -} \ No newline at end of file diff --git a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/image_output_format.proto b/core/model/src/main/proto/com/google/jetpackcamera/model/proto/image_output_format.proto deleted file mode 100644 index b64556b08..000000000 --- a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/image_output_format.proto +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 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. - */ - -syntax = "proto3"; - -option java_package = "com.google.jetpackcamera.model.proto"; -option java_multiple_files = true; - -enum ImageOutputFormat { - IMAGE_OUTPUT_FORMAT_JPEG = 0; - IMAGE_OUTPUT_FORMAT_JPEG_ULTRA_HDR = 1; -} \ No newline at end of file diff --git a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/lens_facing.proto b/core/model/src/main/proto/com/google/jetpackcamera/model/proto/lens_facing.proto deleted file mode 100644 index 2e898a4eb..000000000 --- a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/lens_facing.proto +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 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. - */ - -syntax = "proto3"; - -option java_package = "com.google.jetpackcamera.model.proto"; -option java_multiple_files = true; - -enum LensFacing { - LENS_FACING_BACK = 0; - LENS_FACING_FRONT = 1; -} \ No newline at end of file diff --git a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/low_light_boost_priority.proto b/core/model/src/main/proto/com/google/jetpackcamera/model/proto/low_light_boost_priority.proto deleted file mode 100644 index bd8fd7dbf..000000000 --- a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/low_light_boost_priority.proto +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2025 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. - */ - -syntax = "proto3"; - -option java_package = "com.google.jetpackcamera.model.proto"; -option java_multiple_files = true; - -enum LowLightBoostPriority { - LOW_LIGHT_BOOST_PRIORITY_AE_MODE = 0; - LOW_LIGHT_BOOST_PRIORITY_GOOGLE_PLAY_SERVICES = 1; -} diff --git a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/stabilization_mode.proto b/core/model/src/main/proto/com/google/jetpackcamera/model/proto/stabilization_mode.proto deleted file mode 100644 index bdba01437..000000000 --- a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/stabilization_mode.proto +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 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. - */ - -syntax = "proto3"; - -option java_package = "com.google.jetpackcamera.model.proto"; -option java_multiple_files = true; - -enum StabilizationMode { - STABILIZATION_MODE_UNDEFINED = 0; - STABILIZATION_MODE_AUTO = 1; - STABILIZATION_MODE_OFF = 2; - STABILIZATION_MODE_ON = 3; - STABILIZATION_MODE_HIGH_QUALITY = 4; - STABILIZATION_MODE_OPTICAL = 5; -} \ No newline at end of file diff --git a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/stream_config.proto b/core/model/src/main/proto/com/google/jetpackcamera/model/proto/stream_config.proto deleted file mode 100644 index 28af05d60..000000000 --- a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/stream_config.proto +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2023 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. - */ - -syntax = "proto3"; - -option java_package = "com.google.jetpackcamera.model.proto"; -option java_multiple_files = true; - -enum StreamConfig { - STREAM_CONFIG_UNDEFINED = 0; - STREAM_CONFIG_MULTI_STREAM = 1; - STREAM_CONFIG_SINGLE_STREAM = 2; -} \ No newline at end of file diff --git a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/test_pattern.proto b/core/model/src/main/proto/com/google/jetpackcamera/model/proto/test_pattern.proto deleted file mode 100644 index b74d3d96d..000000000 --- a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/test_pattern.proto +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2023 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. - */ - -syntax = "proto3"; - -option java_package = "com.google.jetpackcamera.model.proto"; -option java_multiple_files = true; - -// Represents the TestPattern sealed interface. -message TestPattern { - oneof pattern { - TestPatternOff off = 1; - TestPatternColorBars color_bars = 2; - TestPatternColorBarsFadeToGray color_bars_fade_to_gray = 3; - TestPatternPN9 pn9 = 4; - TestPatternCustom1 custom1 = 5; - TestPatternSolidColor solid_color = 6; - } -} - -// Corresponds to TestPattern.Off -message TestPatternOff {} - -// Corresponds to TestPattern.ColorBars -message TestPatternColorBars {} - -// Corresponds to TestPattern.ColorBarsFadeToGray -message TestPatternColorBarsFadeToGray {} - -// Corresponds to TestPattern.PN9 -message TestPatternPN9 {} - -// Corresponds to TestPattern.Custom1 -message TestPatternCustom1 {} - -// Corresponds to TestPattern.SolidColor -message TestPatternSolidColor { - uint32 red = 1; - uint32 green_even = 2; - uint32 green_odd = 3; - uint32 blue = 4; -} diff --git a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/video_quality.proto b/core/model/src/main/proto/com/google/jetpackcamera/model/proto/video_quality.proto deleted file mode 100644 index b88b423cc..000000000 --- a/core/model/src/main/proto/com/google/jetpackcamera/model/proto/video_quality.proto +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 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. - */ - -syntax = "proto3"; - -option java_package = "com.google.jetpackcamera.model.proto"; -option java_multiple_files = true; - -enum VideoQuality { - VIDEO_QUALITY_UNSPECIFIED = 0; - VIDEO_QUALITY_SD = 1; - VIDEO_QUALITY_HD = 2; - VIDEO_QUALITY_FHD = 3; - VIDEO_QUALITY_UHD = 4; -} \ No newline at end of file diff --git a/data/settings/build.gradle.kts b/data/settings/build.gradle.kts index 443986762..241a1f1fe 100644 --- a/data/settings/build.gradle.kts +++ b/data/settings/build.gradle.kts @@ -19,7 +19,6 @@ plugins { alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.kapt) alias(libs.plugins.dagger.hilt.android) - alias(libs.plugins.google.protobuf) } android { @@ -76,9 +75,9 @@ dependencies { implementation(libs.dagger.hilt.android) kapt(libs.dagger.hilt.compiler) - // proto datastore + // preferences datastore implementation(libs.androidx.datastore) - implementation(libs.protobuf.kotlin.lite) + implementation(libs.androidx.datastore.preferences) // Testing testImplementation(libs.junit) @@ -94,28 +93,6 @@ dependencies { implementation(project(":core:common")) } -protobuf { - protoc { - artifact = "com.google.protobuf:protoc:3.21.12" - } - - generateProtoTasks { - all().forEach { task -> - task.builtins { - create("java") { - option("lite") - } - } - - task.builtins { - create("kotlin") { - option("lite") - } - } - } - } -} - // Allow references to generated code kapt { correctErrorTypes = true diff --git a/data/settings/src/androidTest/java/com/google/jetpackcamera/settings/DataStoreModuleTest.kt b/data/settings/src/androidTest/java/com/google/jetpackcamera/settings/DataStoreModuleTest.kt index 703783b23..e716e6663 100644 --- a/data/settings/src/androidTest/java/com/google/jetpackcamera/settings/DataStoreModuleTest.kt +++ b/data/settings/src/androidTest/java/com/google/jetpackcamera/settings/DataStoreModuleTest.kt @@ -16,10 +16,10 @@ package com.google.jetpackcamera.settings import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat import com.google.jetpackcamera.settings.testing.FakeDataStoreModule -import com.google.jetpackcamera.settings.testing.FakeJcaSettingsSerializer import java.io.File import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.advanceUntilIdle @@ -43,16 +43,14 @@ class DataStoreModuleTest { } @Test - fun dataStoreModule_read_can_handle_corrupted_file() = runTest { - // should handle exception and replace file information - val dataStore: DataStore = FakeDataStoreModule.provideDataStore( + fun dataStoreModule_can_provide_datastore() = runTest { + val dataStore: DataStore = FakeDataStoreModule.provideDataStore( scope = this.backgroundScope, - serializer = FakeJcaSettingsSerializer(failReadWithCorruptionException = true), file = testFile ) val datastoreValue = dataStore.data.first() advanceUntilIdle() - assertThat(datastoreValue).isEqualTo(JcaSettings.getDefaultInstance()) + assertThat(datastoreValue.asMap()).isEmpty() } } diff --git a/data/settings/src/main/java/com/google/jetpackcamera/settings/DataStoreModule.kt b/data/settings/src/main/java/com/google/jetpackcamera/settings/DataStoreModule.kt index 7f8862455..e26b328ea 100644 --- a/data/settings/src/main/java/com/google/jetpackcamera/settings/DataStoreModule.kt +++ b/data/settings/src/main/java/com/google/jetpackcamera/settings/DataStoreModule.kt @@ -17,9 +17,9 @@ package com.google.jetpackcamera.settings import android.content.Context import androidx.datastore.core.DataStore -import androidx.datastore.core.DataStoreFactory -import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler -import androidx.datastore.dataStoreFile +import androidx.datastore.preferences.core.PreferenceDataStoreFactory +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.preferencesDataStoreFile import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -34,18 +34,15 @@ import kotlinx.coroutines.SupervisorJob @Module @InstallIn(SingletonComponent::class) object DataStoreModule { - private const val FILE_LOCATION = "app_settings.pb" + private const val FILE_LOCATION = "jca_settings" @Provides @Singleton - fun provideDataStore(@ApplicationContext context: Context): DataStore = - DataStoreFactory.create( - corruptionHandler = ReplaceFileCorruptionHandler { JcaSettings.getDefaultInstance() }, - // TODO(b/286245619, kimblebee@): Inject coroutine scope once module providing default IO dispatcher scope is implemented + fun provideDataStore(@ApplicationContext context: Context): DataStore = + PreferenceDataStoreFactory.create( scope = CoroutineScope(Dispatchers.IO + SupervisorJob()), - serializer = JcaSettingsSerializer, produceFile = { - context.dataStoreFile(FILE_LOCATION) + context.preferencesDataStoreFile(FILE_LOCATION) } ) } diff --git a/data/settings/src/main/java/com/google/jetpackcamera/settings/JcaSettingsSerializer.kt b/data/settings/src/main/java/com/google/jetpackcamera/settings/JcaSettingsSerializer.kt deleted file mode 100644 index f84a3248c..000000000 --- a/data/settings/src/main/java/com/google/jetpackcamera/settings/JcaSettingsSerializer.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2023 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 com.google.jetpackcamera.settings - -import androidx.datastore.core.CorruptionException -import androidx.datastore.core.Serializer -import com.google.jetpackcamera.model.UNLIMITED_VIDEO_DURATION -import com.google.jetpackcamera.model.proto.AspectRatio -import com.google.jetpackcamera.model.proto.DarkMode -import com.google.jetpackcamera.model.proto.DynamicRange -import com.google.jetpackcamera.model.proto.FlashMode -import com.google.jetpackcamera.model.proto.ImageOutputFormat -import com.google.jetpackcamera.model.proto.LensFacing -import com.google.jetpackcamera.model.proto.StabilizationMode -import com.google.jetpackcamera.model.proto.StreamConfig -import com.google.jetpackcamera.model.proto.VideoQuality -import com.google.protobuf.InvalidProtocolBufferException -import java.io.InputStream -import java.io.OutputStream -object JcaSettingsSerializer : Serializer { - - override val defaultValue: JcaSettings = JcaSettings.newBuilder() - .setDarkModeStatus(DarkMode.DARK_MODE_DARK) - .setDefaultLensFacing(LensFacing.LENS_FACING_BACK) - .setFlashModeStatus(FlashMode.FLASH_MODE_OFF) - .setAspectRatioStatus(AspectRatio.ASPECT_RATIO_NINE_SIXTEEN) - .setStreamConfigStatus(StreamConfig.STREAM_CONFIG_MULTI_STREAM) - .setStabilizationMode(StabilizationMode.STABILIZATION_MODE_AUTO) - .setDynamicRangeStatus(DynamicRange.DYNAMIC_RANGE_UNSPECIFIED) - .setImageFormatStatus(ImageOutputFormat.IMAGE_OUTPUT_FORMAT_JPEG) - .setMaxVideoDurationMillis(UNLIMITED_VIDEO_DURATION) - .setVideoQuality(VideoQuality.VIDEO_QUALITY_UNSPECIFIED) - .setAudioEnabledStatus(true) - .build() - - override suspend fun readFrom(input: InputStream): JcaSettings { - try { - return JcaSettings.parseFrom(input) - } catch (exception: InvalidProtocolBufferException) { - throw CorruptionException("Cannot read proto.", exception) - } - } - - override suspend fun writeTo(t: JcaSettings, output: OutputStream) = t.writeTo(output) -} diff --git a/data/settings/src/main/java/com/google/jetpackcamera/settings/LocalSettingsRepository.kt b/data/settings/src/main/java/com/google/jetpackcamera/settings/LocalSettingsRepository.kt index 7034f9eba..d8004a214 100644 --- a/data/settings/src/main/java/com/google/jetpackcamera/settings/LocalSettingsRepository.kt +++ b/data/settings/src/main/java/com/google/jetpackcamera/settings/LocalSettingsRepository.kt @@ -16,29 +16,25 @@ package com.google.jetpackcamera.settings import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.intPreferencesKey +import androidx.datastore.preferences.core.longPreferencesKey +import androidx.datastore.preferences.core.stringPreferencesKey import com.google.jetpackcamera.core.common.DefaultCaptureModeOverride import com.google.jetpackcamera.model.AspectRatio import com.google.jetpackcamera.model.CaptureMode import com.google.jetpackcamera.model.DarkMode import com.google.jetpackcamera.model.DynamicRange -import com.google.jetpackcamera.model.DynamicRange.Companion.toProto import com.google.jetpackcamera.model.FlashMode import com.google.jetpackcamera.model.ImageOutputFormat -import com.google.jetpackcamera.model.ImageOutputFormat.Companion.toProto import com.google.jetpackcamera.model.LensFacing -import com.google.jetpackcamera.model.LensFacing.Companion.toProto import com.google.jetpackcamera.model.LowLightBoostPriority -import com.google.jetpackcamera.model.LowLightBoostPriority.Companion.fromProto -import com.google.jetpackcamera.model.LowLightBoostPriority.Companion.toProto import com.google.jetpackcamera.model.StabilizationMode import com.google.jetpackcamera.model.StreamConfig +import com.google.jetpackcamera.model.UNLIMITED_VIDEO_DURATION import com.google.jetpackcamera.model.VideoQuality -import com.google.jetpackcamera.model.VideoQuality.Companion.toProto -import com.google.jetpackcamera.model.proto.AspectRatio as AspectRatioProto -import com.google.jetpackcamera.model.proto.DarkMode as DarkModeProto -import com.google.jetpackcamera.model.proto.FlashMode as FlashModeProto -import com.google.jetpackcamera.model.proto.StabilizationMode as StabilizationModeProto -import com.google.jetpackcamera.model.proto.StreamConfig as StreamConfigProto import com.google.jetpackcamera.settings.model.CameraAppSettings import javax.inject.Inject import kotlinx.coroutines.flow.first @@ -48,42 +44,58 @@ import kotlinx.coroutines.flow.map * Implementation of [SettingsRepository] with locally stored settings. */ class LocalSettingsRepository @Inject constructor( - private val jcaSettings: DataStore, + private val jcaSettings: DataStore, @DefaultCaptureModeOverride private val defaultCaptureModeOverride: CaptureMode -) : - SettingsRepository { +) : SettingsRepository { + + companion object { + private val KEY_LENS_FACING = stringPreferencesKey("lens_facing") + private val KEY_DARK_MODE = stringPreferencesKey("dark_mode") + private val KEY_FLASH_MODE = stringPreferencesKey("flash_mode") + private val KEY_ASPECT_RATIO = stringPreferencesKey("aspect_ratio") + private val KEY_STREAM_CONFIG = stringPreferencesKey("stream_config") + private val KEY_STABILIZATION_MODE = stringPreferencesKey("stabilization_mode") + private val KEY_DYNAMIC_RANGE = stringPreferencesKey("dynamic_range") + private val KEY_VIDEO_QUALITY = stringPreferencesKey("video_quality") + private val KEY_IMAGE_FORMAT = stringPreferencesKey("image_format") + private val KEY_MAX_VIDEO_DURATION = longPreferencesKey("max_video_duration") + private val KEY_AUDIO_ENABLED = booleanPreferencesKey("audio_enabled") + private val KEY_LOW_LIGHT_BOOST_PRIORITY = stringPreferencesKey("low_light_boost_priority") + private val KEY_TARGET_FRAME_RATE = intPreferencesKey("target_frame_rate") + + private inline fun > String?.toEnumOrDefault(default: T): T { + if (this == null) return default + return enumValues().firstOrNull { it.name == this } ?: default + } + } override val defaultCameraAppSettings = jcaSettings.data - .map { + .map { preferences -> CameraAppSettings( - cameraLensFacing = LensFacing.fromProto(it.defaultLensFacing), - darkMode = when (it.darkModeStatus) { - DarkModeProto.DARK_MODE_DARK -> DarkMode.DARK - DarkModeProto.DARK_MODE_LIGHT -> DarkMode.LIGHT - DarkModeProto.DARK_MODE_SYSTEM -> DarkMode.SYSTEM - else -> DarkMode.DARK - }, - flashMode = when (it.flashModeStatus) { - FlashModeProto.FLASH_MODE_AUTO -> FlashMode.AUTO - FlashModeProto.FLASH_MODE_ON -> FlashMode.ON - FlashModeProto.FLASH_MODE_OFF -> FlashMode.OFF - FlashModeProto.FLASH_MODE_LOW_LIGHT_BOOST -> FlashMode.LOW_LIGHT_BOOST - else -> FlashMode.OFF - }, - aspectRatio = AspectRatio.fromProto(it.aspectRatioStatus), - stabilizationMode = StabilizationMode.fromProto(it.stabilizationMode), - targetFrameRate = it.targetFrameRate, - streamConfig = when (it.streamConfigStatus) { - StreamConfigProto.STREAM_CONFIG_SINGLE_STREAM -> StreamConfig.SINGLE_STREAM - StreamConfigProto.STREAM_CONFIG_MULTI_STREAM -> StreamConfig.MULTI_STREAM - else -> StreamConfig.MULTI_STREAM - }, - lowLightBoostPriority = fromProto(it.lowLightBoostPriority), - dynamicRange = DynamicRange.fromProto(it.dynamicRangeStatus), - imageFormat = ImageOutputFormat.fromProto(it.imageFormatStatus), - maxVideoDurationMillis = it.maxVideoDurationMillis, - videoQuality = VideoQuality.fromProto(it.videoQuality), - audioEnabled = it.audioEnabledStatus, + cameraLensFacing = preferences[KEY_LENS_FACING] + .toEnumOrDefault(LensFacing.BACK), + darkMode = preferences[KEY_DARK_MODE] + .toEnumOrDefault(DarkMode.DARK), + flashMode = preferences[KEY_FLASH_MODE] + .toEnumOrDefault(FlashMode.OFF), + aspectRatio = preferences[KEY_ASPECT_RATIO] + .toEnumOrDefault(AspectRatio.NINE_SIXTEEN), + stabilizationMode = preferences[KEY_STABILIZATION_MODE] + .toEnumOrDefault(StabilizationMode.AUTO), + targetFrameRate = preferences[KEY_TARGET_FRAME_RATE] ?: 0, + streamConfig = preferences[KEY_STREAM_CONFIG] + .toEnumOrDefault(StreamConfig.MULTI_STREAM), + lowLightBoostPriority = preferences[KEY_LOW_LIGHT_BOOST_PRIORITY] + .toEnumOrDefault(LowLightBoostPriority.PRIORITIZE_AE_MODE), + dynamicRange = preferences[KEY_DYNAMIC_RANGE] + .toEnumOrDefault(DynamicRange.SDR), + imageFormat = preferences[KEY_IMAGE_FORMAT] + .toEnumOrDefault(ImageOutputFormat.JPEG), + maxVideoDurationMillis = preferences[KEY_MAX_VIDEO_DURATION] + ?: UNLIMITED_VIDEO_DURATION, + videoQuality = preferences[KEY_VIDEO_QUALITY] + .toEnumOrDefault(VideoQuality.UNSPECIFIED), + audioEnabled = preferences[KEY_AUDIO_ENABLED] ?: true, captureMode = defaultCaptureModeOverride ) } @@ -92,132 +104,80 @@ class LocalSettingsRepository @Inject constructor( defaultCameraAppSettings.first() override suspend fun updateDefaultLensFacing(lensFacing: LensFacing) { - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setDefaultLensFacing(lensFacing.toProto()) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_LENS_FACING] = lensFacing.name } } override suspend fun updateDarkModeStatus(darkMode: DarkMode) { - val newStatus = when (darkMode) { - DarkMode.DARK -> DarkModeProto.DARK_MODE_DARK - DarkMode.LIGHT -> DarkModeProto.DARK_MODE_LIGHT - DarkMode.SYSTEM -> DarkModeProto.DARK_MODE_SYSTEM - } - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setDarkModeStatus(newStatus) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_DARK_MODE] = darkMode.name } } override suspend fun updateFlashModeStatus(flashMode: FlashMode) { - val newStatus = when (flashMode) { - FlashMode.AUTO -> FlashModeProto.FLASH_MODE_AUTO - FlashMode.ON -> FlashModeProto.FLASH_MODE_ON - FlashMode.OFF -> FlashModeProto.FLASH_MODE_OFF - FlashMode.LOW_LIGHT_BOOST -> FlashModeProto.FLASH_MODE_LOW_LIGHT_BOOST - } - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setFlashModeStatus(newStatus) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_FLASH_MODE] = flashMode.name } } override suspend fun updateTargetFrameRate(targetFrameRate: Int) { - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setTargetFrameRate(targetFrameRate) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_TARGET_FRAME_RATE] = targetFrameRate } } override suspend fun updateAspectRatio(aspectRatio: AspectRatio) { - val newStatus = when (aspectRatio) { - AspectRatio.NINE_SIXTEEN -> AspectRatioProto.ASPECT_RATIO_NINE_SIXTEEN - AspectRatio.THREE_FOUR -> AspectRatioProto.ASPECT_RATIO_THREE_FOUR - AspectRatio.ONE_ONE -> AspectRatioProto.ASPECT_RATIO_ONE_ONE - } - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setAspectRatioStatus(newStatus) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_ASPECT_RATIO] = aspectRatio.name } } override suspend fun updateStreamConfig(streamConfig: StreamConfig) { - val newStatus = when (streamConfig) { - StreamConfig.MULTI_STREAM -> StreamConfigProto.STREAM_CONFIG_MULTI_STREAM - StreamConfig.SINGLE_STREAM -> StreamConfigProto.STREAM_CONFIG_SINGLE_STREAM - } - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setStreamConfigStatus(newStatus) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_STREAM_CONFIG] = streamConfig.name } } override suspend fun updateStabilizationMode(stabilizationMode: StabilizationMode) { - val newStatus = when (stabilizationMode) { - StabilizationMode.OFF -> StabilizationModeProto.STABILIZATION_MODE_OFF - StabilizationMode.AUTO -> StabilizationModeProto.STABILIZATION_MODE_AUTO - StabilizationMode.ON -> StabilizationModeProto.STABILIZATION_MODE_ON - StabilizationMode.HIGH_QUALITY -> StabilizationModeProto.STABILIZATION_MODE_HIGH_QUALITY - StabilizationMode.OPTICAL -> StabilizationModeProto.STABILIZATION_MODE_OPTICAL - } - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setStabilizationMode(newStatus) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_STABILIZATION_MODE] = stabilizationMode.name } } override suspend fun updateDynamicRange(dynamicRange: DynamicRange) { - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setDynamicRangeStatus(dynamicRange.toProto()) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_DYNAMIC_RANGE] = dynamicRange.name } } override suspend fun updateImageFormat(imageFormat: ImageOutputFormat) { - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setImageFormatStatus(imageFormat.toProto()) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_IMAGE_FORMAT] = imageFormat.name } } + override suspend fun updateMaxVideoDuration(durationMillis: Long) { - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setMaxVideoDurationMillis(durationMillis) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_MAX_VIDEO_DURATION] = durationMillis } } override suspend fun updateVideoQuality(videoQuality: VideoQuality) { - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setVideoQuality(videoQuality.toProto()) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_VIDEO_QUALITY] = videoQuality.name } } override suspend fun updateLowLightBoostPriority(lowLightBoostPriority: LowLightBoostPriority) { - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setLowLightBoostPriority(lowLightBoostPriority.toProto()) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_LOW_LIGHT_BOOST_PRIORITY] = lowLightBoostPriority.name } } override suspend fun updateAudioEnabled(isAudioEnabled: Boolean) { - jcaSettings.updateData { currentSettings -> - currentSettings.toBuilder() - .setAudioEnabledStatus(isAudioEnabled) - .build() + jcaSettings.edit { preferences -> + preferences[KEY_AUDIO_ENABLED] = isAudioEnabled } } } diff --git a/data/settings/testing/build.gradle.kts b/data/settings/testing/build.gradle.kts index 0eb033d6e..a1f1cb624 100644 --- a/data/settings/testing/build.gradle.kts +++ b/data/settings/testing/build.gradle.kts @@ -54,5 +54,5 @@ dependencies { implementation(libs.kotlinx.coroutines.core) implementation(libs.androidx.datastore) - implementation(libs.protobuf.kotlin.lite) + implementation(libs.androidx.datastore.preferences) } diff --git a/data/settings/testing/src/main/java/com/google/jetpackcamera/settings/testing/FakeDataStoreModule.kt b/data/settings/testing/src/main/java/com/google/jetpackcamera/settings/testing/FakeDataStoreModule.kt index 7c07edfe6..031ee1568 100644 --- a/data/settings/testing/src/main/java/com/google/jetpackcamera/settings/testing/FakeDataStoreModule.kt +++ b/data/settings/testing/src/main/java/com/google/jetpackcamera/settings/testing/FakeDataStoreModule.kt @@ -16,23 +16,17 @@ package com.google.jetpackcamera.settings.testing import androidx.datastore.core.DataStore -import androidx.datastore.core.DataStoreFactory -import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler -import com.google.jetpackcamera.settings.JcaSettings +import androidx.datastore.preferences.core.PreferenceDataStoreFactory +import androidx.datastore.preferences.core.Preferences import java.io.File import kotlinx.coroutines.CoroutineScope /** test implementation of DataStoreModule */ object FakeDataStoreModule { - fun provideDataStore( - scope: CoroutineScope, - serializer: FakeJcaSettingsSerializer, - file: File - ): DataStore = DataStoreFactory.create( - corruptionHandler = ReplaceFileCorruptionHandler { JcaSettings.getDefaultInstance() }, - scope = scope, - serializer = serializer, - produceFile = { file } - ) + fun provideDataStore(scope: CoroutineScope, file: File): DataStore = + PreferenceDataStoreFactory.create( + scope = scope, + produceFile = { file } + ) } diff --git a/data/settings/testing/src/main/java/com/google/jetpackcamera/settings/testing/FakeJcaSettingsSerializer.kt b/data/settings/testing/src/main/java/com/google/jetpackcamera/settings/testing/FakeJcaSettingsSerializer.kt deleted file mode 100644 index 5b319f9d4..000000000 --- a/data/settings/testing/src/main/java/com/google/jetpackcamera/settings/testing/FakeJcaSettingsSerializer.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2023 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 com.google.jetpackcamera.settings.testing - -import androidx.datastore.core.CorruptionException -import androidx.datastore.core.Serializer -import com.google.jetpackcamera.model.UNLIMITED_VIDEO_DURATION -import com.google.jetpackcamera.model.proto.AspectRatio -import com.google.jetpackcamera.model.proto.DarkMode -import com.google.jetpackcamera.model.proto.DynamicRange -import com.google.jetpackcamera.model.proto.FlashMode -import com.google.jetpackcamera.model.proto.ImageOutputFormat -import com.google.jetpackcamera.model.proto.LensFacing -import com.google.jetpackcamera.model.proto.StabilizationMode -import com.google.jetpackcamera.model.proto.StreamConfig -import com.google.jetpackcamera.model.proto.VideoQuality -import com.google.jetpackcamera.settings.JcaSettings -import com.google.protobuf.InvalidProtocolBufferException -import java.io.IOException -import java.io.InputStream -import java.io.OutputStream - -class FakeJcaSettingsSerializer(var failReadWithCorruptionException: Boolean = false) : - Serializer { - - override val defaultValue: JcaSettings = JcaSettings.newBuilder() - .setDarkModeStatus(DarkMode.DARK_MODE_SYSTEM) - .setDefaultLensFacing(LensFacing.LENS_FACING_BACK) - .setFlashModeStatus(FlashMode.FLASH_MODE_OFF) - .setAspectRatioStatus(AspectRatio.ASPECT_RATIO_NINE_SIXTEEN) - .setStreamConfigStatus(StreamConfig.STREAM_CONFIG_MULTI_STREAM) - .setStabilizationMode(StabilizationMode.STABILIZATION_MODE_AUTO) - .setDynamicRangeStatus(DynamicRange.DYNAMIC_RANGE_SDR) - .setVideoQuality(VideoQuality.VIDEO_QUALITY_UNSPECIFIED) - .setImageFormatStatus(ImageOutputFormat.IMAGE_OUTPUT_FORMAT_JPEG) - .setMaxVideoDurationMillis(UNLIMITED_VIDEO_DURATION) - .build() - - override suspend fun readFrom(input: InputStream): JcaSettings { - if (failReadWithCorruptionException) { - throw CorruptionException( - "Corruption Exception", - IOException() - ) - } - try { - return JcaSettings.parseFrom(input) - } catch (exception: InvalidProtocolBufferException) { - throw CorruptionException("Cannot read proto.", exception) - } - } - - override suspend fun writeTo(t: JcaSettings, output: OutputStream) = t.writeTo(output) -} diff --git a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/navigation/DebugSettingsNavType.kt b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/navigation/DebugSettingsNavType.kt index d2c4c5dfa..18f823ffc 100644 --- a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/navigation/DebugSettingsNavType.kt +++ b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/navigation/DebugSettingsNavType.kt @@ -18,7 +18,6 @@ package com.google.jetpackcamera.feature.preview.navigation import android.os.Bundle import androidx.navigation.NavType import com.google.jetpackcamera.model.DebugSettings -import com.google.jetpackcamera.model.DebugSettings.Companion.encodeAsByteArray import com.google.jetpackcamera.model.DebugSettings.Companion.encodeAsString /** @@ -31,15 +30,15 @@ internal object DebugSettingsNavType : NavType(isNullableAllowed * Puts the [DebugSettings] value into the Bundle by converting to Proto and serializing. */ override fun put(bundle: Bundle, key: String, value: DebugSettings) { - bundle.putByteArray(key, value.encodeAsByteArray()) + bundle.putString(key, value.encodeAsString()) } /** * Gets the [DebugSettings] value from the Bundle by deserializing the Proto. */ override fun get(bundle: Bundle, key: String): DebugSettings? { - return bundle.getByteArray(key)?.let { bytes -> - DebugSettings.parseFromByteArray(bytes) + return bundle.getString(key)?.let { str -> + DebugSettings.parseFromString(str) } } diff --git a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/navigation/PreviewNavigation.kt b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/navigation/PreviewNavigation.kt index 60b91ba52..1021d6e68 100644 --- a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/navigation/PreviewNavigation.kt +++ b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/navigation/PreviewNavigation.kt @@ -188,5 +188,5 @@ internal fun SavedStateHandle.getCaptureUris(defaultIfMissing: List = empty internal fun SavedStateHandle.getDebugSettings( defaultIfMissing: DebugSettings = DebugSettings() -): DebugSettings = get(ARG_DEBUG_SETTINGS)?.let(DebugSettings::parseFromByteArray) +): DebugSettings = get(ARG_DEBUG_SETTINGS)?.let(DebugSettings::parseFromString) ?: defaultIfMissing diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1c4f9b336..1af439742 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -63,6 +63,7 @@ androidx-annotation = { module = "androidx.annotation:annotation", version.ref = androidx-benchmark-macro-junit4 = { module = "androidx.benchmark:benchmark-macro-junit4", version.ref = "androidxBenchmark" } androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidxCoreKtx" } androidx-datastore = { module = "androidx.datastore:datastore", version.ref = "androidxDatastore" } +androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "androidxDatastore" } androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidxTestEspresso" } androidx-graphics-core = { module = "androidx.graphics:graphics-core", version.ref = "androidxGraphicsCore" } androidx-junit = { module = "androidx.test.ext:junit", version.ref = "androidxTestJunit" }