-
Notifications
You must be signed in to change notification settings - Fork 61
developer options api #493
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a79130f
33c12ab
2d3a7e9
13670e4
747d67c
00a7b07
e538048
79b032d
3ae47cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| /build |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| /* | ||
| * Copyright (C) 2026 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. | ||
| */ | ||
| plugins { | ||
| alias(libs.plugins.android.library) | ||
| alias(libs.plugins.kotlin.android) | ||
| } | ||
|
|
||
| android { | ||
| namespace = "com.google.jetpackcamera.settings.api" | ||
| compileSdk = 35 | ||
|
|
||
| defaultConfig { | ||
| minSdk = 23 | ||
| targetSdk = 35 | ||
|
|
||
| testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" | ||
| consumerProguardFiles("consumer-rules.pro") | ||
| } | ||
|
|
||
| buildTypes { | ||
| release { | ||
| isMinifyEnabled = false | ||
| proguardFiles( | ||
| getDefaultProguardFile("proguard-android-optimize.txt"), | ||
| "proguard-rules.pro" | ||
| ) | ||
| } | ||
| } | ||
| compileOptions { | ||
| sourceCompatibility = JavaVersion.VERSION_11 | ||
| targetCompatibility = JavaVersion.VERSION_11 | ||
| } | ||
| kotlinOptions { | ||
| jvmTarget = "11" | ||
| } | ||
| } | ||
|
|
||
| dependencies { | ||
| implementation(libs.androidx.core.ktx) | ||
| implementation(libs.androidx.appcompat) | ||
| implementation(libs.material) | ||
| testImplementation(libs.junit) | ||
| androidTestImplementation(libs.androidx.junit) | ||
| androidTestImplementation(libs.androidx.espresso.core) | ||
|
|
||
| // Access Model data | ||
| implementation(project(":core:model")) | ||
| implementation(project(":core:common")) | ||
| implementation(project(":data:settings")) | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # Add project specific ProGuard rules here. | ||
| # You can control the set of applied configuration files using the | ||
| # proguardFiles setting in build.gradle. | ||
| # | ||
| # For more details, see | ||
| # http://developer.android.com/guide/developing/tools/proguard.html | ||
|
|
||
| # If your project uses WebView with JS, uncomment the following | ||
| # and specify the fully qualified class name to the JavaScript interface | ||
| # class: | ||
| #-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
| # public *; | ||
| #} | ||
|
|
||
| # Uncomment this to preserve the line number information for | ||
| # debugging stack traces. | ||
| #-keepattributes SourceFile,LineNumberTable | ||
|
|
||
| # If you keep the line number information, uncomment this to | ||
| # hide the original source file name. | ||
| #-renamesourcefileattribute SourceFile |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <!-- | ||
| ~ Copyright (C) 2026 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. | ||
| --> | ||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
|
|
||
| </manifest> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| /* | ||
| * Copyright (C) 2026 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.api | ||
|
|
||
| import com.google.jetpackcamera.model.AspectRatio | ||
| import com.google.jetpackcamera.model.CaptureMode | ||
| import com.google.jetpackcamera.model.DynamicRange | ||
| import com.google.jetpackcamera.model.FlashMode | ||
| import com.google.jetpackcamera.model.ImageOutputFormat | ||
| import com.google.jetpackcamera.settings.model.CameraAppSettings | ||
| import com.google.jetpackcamera.settings.model.DEFAULT_CAMERA_APP_SETTINGS | ||
|
|
||
| /** | ||
| * Defines a configuration for the Jetpack Camera App that can be used by developers | ||
| * to override the default app settings. | ||
| */ | ||
| data class DeveloperAppConfig( | ||
| val captureMode: SettingConfig<CaptureMode>, | ||
| val aspectRatio: SettingConfig<AspectRatio>, | ||
| val flashMode: SettingConfig<FlashMode>, | ||
| val audio: SettingConfig<Boolean>, | ||
| val hdrEnabled: SettingConfig<Boolean> | ||
| ) { | ||
| // Ensures that all individual setting configurations are valid. | ||
| init { | ||
| fun <T : Any> SettingConfig<T>.containsIfOptionsEnabled(options: Set<T>): Boolean { | ||
| return when (val restriction = this.uiRestriction) { | ||
| is OptionRestrictionConfig.OptionsEnabled -> { | ||
| restriction.enabledOptions.containsAll(options) | ||
| } | ||
|
|
||
| else -> true | ||
| } | ||
| } | ||
|
|
||
| require(flashMode.containsIfOptionsEnabled(setOf(FlashMode.OFF))) | ||
| } | ||
|
|
||
| companion object { | ||
| // Provides a foundation based on JCA's DEFAULT_CAMERA_APP_SETTINGS | ||
| val LibraryDefaults: DeveloperAppConfig = DeveloperAppConfig( | ||
| aspectRatio = SettingConfig(DEFAULT_CAMERA_APP_SETTINGS.aspectRatio), | ||
| flashMode = SettingConfig(DEFAULT_CAMERA_APP_SETTINGS.flashMode), | ||
| captureMode = SettingConfig(DEFAULT_CAMERA_APP_SETTINGS.captureMode), | ||
| audio = SettingConfig(DEFAULT_CAMERA_APP_SETTINGS.audioEnabled), | ||
| hdrEnabled = SettingConfig( | ||
| DEFAULT_CAMERA_APP_SETTINGS.dynamicRange != DynamicRange.SDR | ||
| ) | ||
| ) | ||
| } | ||
|
|
||
| /** | ||
| * Converts this [DeveloperAppConfig] into a [CameraAppSettings] object. | ||
| * | ||
| * This function maps the developer-defined settings to the internal camera app settings model. | ||
| */ | ||
| fun toCameraAppSettings( | ||
| defaultSettings: CameraAppSettings = DEFAULT_CAMERA_APP_SETTINGS | ||
| ): CameraAppSettings { | ||
| val imageOutputFormat = if (this.hdrEnabled.defaultValue) { | ||
| ImageOutputFormat.JPEG_ULTRA_HDR | ||
| } else { | ||
| ImageOutputFormat.JPEG | ||
| } | ||
|
|
||
| val dynamicRange = | ||
| if (this.hdrEnabled.defaultValue) DynamicRange.HLG10 else DynamicRange.SDR | ||
|
|
||
| return defaultSettings.copy( | ||
| aspectRatio = this.aspectRatio.defaultValue, | ||
| flashMode = this.flashMode.defaultValue, | ||
| captureMode = this.captureMode.defaultValue, | ||
| audioEnabled = this.audio.defaultValue, | ||
| imageFormat = imageOutputFormat, | ||
| dynamicRange = dynamicRange | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Represents a single configurable setting in the application, including its | ||
| * default value and any UI restrictions that apply to it. | ||
| * | ||
| * @param defaultValue The initial value for this setting. | ||
| * @param uiRestriction The restrictions applied to this setting in the UI. | ||
| */ | ||
| data class SettingConfig<T>( | ||
| val defaultValue: T, | ||
| val uiRestriction: OptionRestrictionConfig<T> = OptionRestrictionConfig.NotRestricted() | ||
| ) { | ||
| init { | ||
| // Validate that if options are enabled for this setting, the default value | ||
| // is always included in the set of enabled options. | ||
| (uiRestriction as? OptionRestrictionConfig.OptionsEnabled)?.let { | ||
| require( | ||
| uiRestriction.enabledOptions.size >= 2 && | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The requirement for |
||
| uiRestriction.enabledOptions.contains( | ||
| defaultValue | ||
| ) | ||
| ) { | ||
| "OptionsRestrictionConfig.OptionsEnabled#enabledOptions must also contain the defaultValue" | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| sealed interface OptionRestrictionConfig<T> { | ||
| /** All device-supported options are available. */ | ||
| class NotRestricted<T> : OptionRestrictionConfig<T> | ||
|
|
||
| /** The entire setting is unavailable and hidden from the UI. */ | ||
| class FullyRestricted<T> : OptionRestrictionConfig<T> | ||
|
|
||
| /** ONLY the options in this set are allowed, if supported by the device. */ | ||
| data class OptionsEnabled<T>(val enabledOptions: Set<T>) : OptionRestrictionConfig<T> { | ||
| init { | ||
| require(enabledOptions.isNotEmpty()) { | ||
| "enabledOptions must not be empty. " + | ||
| "Use FullyRestricted to disable the feature." | ||
| } | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Java version (11) for this new module is inconsistent with the rest of the project, which uses Java 17 (e.g., in
app/build.gradle.kts). It's recommended to keep the toolchain and compatibility versions consistent across all modules to avoid potential build or runtime issues.