Conversation
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces a new DeveloperAppConfig API to allow overriding default camera settings and restricting UI options, which is integrated into the PreviewViewModel and navigation logic. Several issues were identified in the review: a compilation error in PreviewViewModelTest due to passing null to a non-nullable parameter, inconsistent Java toolchain versions in the new module, and incorrect test tags and string resources in the UI components. Additionally, the OptionRestrictionConfig validation was found to be overly restrictive, and a potential runtime crash was noted in the CaptureModeUiStateAdapter.
Kimblebee
changed the base branch from
main
to
kim/refactor/quickSettings/button-rows
July 6, 2026 13:48
Kimblebee
force-pushed
the
kim/refactor/quickSettings/button-rows
branch
from
July 29, 2026 17:41
2370297 to
bfd867e
Compare
Kimblebee
marked this pull request as ready for review
August 14, 2026 18:20
Kimblebee
force-pushed
the
kim/refactor/quickSettings/button-rows
branch
from
August 26, 2026 22:00
5d67110 to
3b7dfd5
Compare
Base automatically changed from
kim/refactor/quickSettings/button-rows
to
main
August 31, 2026 17:19
Kimblebee
force-pushed
the
kim/developerOptions/hybrid-api
branch
from
September 3, 2026 22:29
5a4bf7f to
f977fd1
Compare
Kimblebee
force-pushed
the
kim/developerOptions/hybrid-api
branch
from
September 4, 2026 03:49
f977fd1 to
1276240
Compare
…, and safety checks
…and fix runtime exception
…outRestrictions, and cleanup teardown
… AppModule config binding
…ityConfig and uiVisibility, add Hidden and UNKNOWN fallbacks - Rename OptionRestrictionConfig to OptionAvailabilityConfig and uiRestriction to uiVisibility - Rename FullyRestricted to Hidden and remove artificial invoke() operator on singleton data objects - Validate that OptionsEnabled contains at least 2 options and that flashMode defaults to OFF when Hidden - Replace unhandled RuntimeException in CaptureModeUiStateAdapter with DisabledReason.UNKNOWN - Annotate providesDeveloperAppConfig() with @singleton in AppModule - Update all unit tests across data:settings:api, feature:preview, and ui:uistateadapter:capture
temcguir
requested changes
Sep 10, 2026
…hybrid-api # Conflicts: # feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt # feature/preview/src/test/java/com/google/jetpackcamera/feature/preview/PreviewViewModelTest.kt # ui/uistateadapter/capture/src/main/java/com/google/jetpackcamera/ui/uistateadapter/capture/compound/CaptureUiStateAdapter.kt # ui/uistateadapter/capture/src/test/java/com/google/jetpackcamera/ui/uistateadapter/capture/CaptureUiStateAdapterTest.kt
Remove KEY_USE_DEVELOPER_CONFIG Intent extra and navigation argument plumbing across MainActivity, JcaApp, and PreviewNavigation. DeveloperAppConfig is now injected directly via Hilt into PreviewViewModel and applied unconditionally. Updates PreviewViewModelTest to verify restrictions directly from injected appConfig.
…make properties nullable Rename DeveloperAppConfig to CameraAppConfig (matching Jetpack/CameraX conventions) and update property names (imageFormat, dynamicRange). Make all properties nullable with a null default in CameraAppConfig, ensuring toCameraAppSettings() preserves persistent user preferences when individual settings are unconstrained. Update AppModule, PreviewViewModel, CaptureUiStateAdapter, and associated unit tests.
… and update E2E tests - Rename restrictionConfig to visibilityConfig and make it nullable with null default in CaptureModeUiStateAdapter. - Guard CaptureModeUiState.from against unselectable active capture mode, returning Unavailable to prevent IllegalStateException. - Update CaptureModeSettingsTest to verify that the capture mode toggle switch is removed (assertDoesNotExist) rather than disabled when switching is not supported. - Rename providesDeveloperAppConfig to providesCameraAppConfig in AppModule.
…nd remove :data:settings:api Move CameraAppConfig and its unit tests into :core:settings under the com.google.jetpackcamera.settings.model package, co-located with CameraAppSettings and Constraints. Remove the obsolete :data:settings:api module and its references from settings.gradle.kts, app, feature:preview, and ui:uistateadapter:capture. This resolves the architectural layering inversion where UI state adapters depended on a data-layer module.
…ystemRepository - Inject CameraAppConfig into CameraXCameraSystemRepository via CameraModule. - Apply cameraAppConfig.toCameraAppSettings(...) to initial settings during lazy camera startup. - Add testCameraAppConfig test override hook in AppModule for instrumentation tests. - Fix missing composeTestRule prefix in CaptureModeSettingsTest.
…nts when hidden - Require ImageOutputFormat.JPEG when imageFormat is Hidden or OptionsEnabled. - Require DynamicRange.SDR when dynamicRange is Hidden or OptionsEnabled. - Add unit tests verifying these invariants in CameraAppConfigTest.
…tory - Add getCameraSystem_withCameraAppConfig_appliesDefaultValues() verifying startup initialization passes overridden default settings to CameraSystem.
- Add FlashModeAppConfigDeviceTest parameterized across BACK and FRONT lenses. - Add CaptureModeAppConfigDeviceTest verifying default, hidden, and filtered capture modes. - Add HdrAppConfigDeviceTest parameterized across BACK and FRONT lenses for image and video HDR. - Add AspectRatioAppConfigDeviceTest verifying aspect ratio defaults in Quick Settings.
- Rename OptionAvailabilityConfig to OptionVisibility. - Rename OptionAvailabilityConfig.NotRestricted to OptionVisibility.Visible. - Rename OptionAvailabilityConfig.OptionsEnabled to OptionVisibility.Only. - Rename SettingConfig.uiVisibility to SettingConfig.visibility. - Update all usage across UI state adapters, viewmodels, and tests.
- Add OptionVisibility.from(options) to safely fall back to Hidden when fewer than 2 options are provided, preventing runtime exceptions. - Add unit test coverage in CameraFeaturePolicyTest.
Moves developer baseline defaults and restriction policies into the settings layer so that unconfigured user preferences from DataStore are preserved instead of wiped by ad-hoc ViewModel / Camera reconciliation. - PrefsDataStoreSettingsDataSource: falls back to CameraFeaturePolicy baseline defaults for unconfigured preferences. - LocalSettingsRepository: intercepts defaultCameraAppSettings flow to continuously enforce OptionVisibility restrictions (Hidden/Only). - CameraXCameraSystemRepository: removes ad-hoc toCameraAppSettings() reconciliation and initializes directly from settingsRepository. - Adds comprehensive unit tests in LocalSettingsRepositoryTest and verifies DataStore behavior in instrumented tests.
…rols Connects OptionVisibility restrictions for AspectRatio from CameraFeaturePolicy into AspectRatioUiState and QuickSettings: - AspectRatioUiStateAdapter: accepts an optional visibilityConfig parameter. When set to OptionVisibility.Hidden or when device/policy restricts available aspect ratios to <= 1 option, returns AspectRatioUiState.Unavailable so that the Aspect Ratio row is hidden from Quick Settings. When restricted by OptionVisibility.Only, limits available options and falls back to a valid selection. - CaptureUiStateAdapter: wires appConfig.aspectRatio.visibility into quickSettingsUiState's AspectRatioUiState, while ensuring previewDisplayUiState continues to receive an Available AspectRatioUiState with the selected aspect ratio so that the viewfinder surface renders properly. - AppModule: cleans up manual testing overrides and defaults to clean CameraFeaturePolicy(). - AspectRatioAppConfigDeviceTest: adds Section B (Hidden) and Section C (OptionsEnabled / Filtering) E2E device tests verifying that the Aspect Ratio quick settings row is absent when hidden and constrained when restricted. - AspectRatioUiStateAdapterTest & CaptureUiStateAdapterTest: adds unit tests verifying UI state adapter emission for hidden, only, and default visibilities.
Clean up remaining vestigial references to CameraAppConfig and appConfig across the codebase: - Rename parameters and arguments in CaptureUiStateAdapter and PreviewViewModel from appConfig to cameraFeaturePolicy. - Update unit tests in CaptureUiStateAdapterTest, PreviewViewModelTest, CameraFeaturePolicyTest, and CameraXCameraSystemRepositoryTest. - Move androidTest package from com.google.jetpackcamera.appconfig to com.google.jetpackcamera.featurepolicy and rename device test classes to *FeaturePolicyDeviceTest.
Add notes on: - QuickSettingsUiState.Companion.from: returning QuickSettingsUiState.Unavailable when all option rows (aspectRatio, captureMode, flashMode, hdr) are Unavailable. - PreviewScreen: checking quickSettingsState.value is Available in isQuickSettingsVisible to hide the quick settings toggle button when all rows are unavailable.
temcguir
requested changes
Sep 18, 2026
- Drop Hidden checks in CameraFeaturePolicy requiring JPEG or SDR defaults, enabling client apps to default/lock to Ultra HDR and HLG10 video. - Update CameraFeaturePolicyTest to verify Hidden Ultra HDR and HLG10 success. - Enforce capture mode restrictions in LocalSettingsRepository to preserve valid selections under OptionVisibility.Only. - Rename visibilityConfig to optionVisibility in CaptureModeToggleUiState.Companion.from and internal helpers. - Document binary quick-toggle contract in CaptureModeToggleUiState KDoc. - Remove unreachable OptionVisibility.Hidden checks from getCaptureModeDisabledReason. - Update QuickSettingsUiStateAdapter and PreviewScreen TODOs regarding follow-up settings navigation. - Clean up unused legacy test tags in TestTags.kt.
… KDocs and expand test coverage - Add prominent Safety Notice to OptionVisibility.Only advising callers to prefer OptionVisibility.from for dynamically resolved option sets. - Document secondary vararg constructor of OptionVisibility.Only and add cross-referencing @see links. - Update CameraFeaturePolicy example to demonstrate OptionVisibility.from. - Add unit tests in CaptureModeUiStateAdapterTest covering concurrent camera DUAL and HDR conflict disabled reasons. - Assert strict deterministic fallback order in AspectRatioUiStateAdapterTest.
…gs when unavailable and align optionVisibility params - Check quickSettingsState.value is QuickSettingsUiState.Available in isQuickSettingsVisible to hide quick settings toggle button when unavailable. - Align remaining visibilityConfig parameters to optionVisibility across AspectRatioUiStateAdapter, FlashModeUiStateAdapter, HdrUiStateAdapter, and CaptureUiStateAdapter. - Update FlashModeUiStateAdapterTest and HdrUiStateAdapterTest to match new parameter names.
Kimblebee
force-pushed
the
kim/developerOptions/hybrid-api
branch
from
September 22, 2026 00:16
754f643 to
76e2105
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces
CameraFeaturePolicyin:core:settingsto allow developer options, embedding applications, and test harnesses to configure default camera settings and control UI option visibility.This decouples the baseline camera session state (
defaultValue) from Compose UI presentation (OptionVisibility), enabling controls to be shown normally, hidden entirely, or restricted to a specific whitelist of options with guaranteed domain safety and graceful fallbacks.Key Changes
Configuration & Models (
core:settings):CameraFeaturePolicywith nullable properties:captureMode,aspectRatio,flashMode,imageFormat, anddynamicRange.SettingConfig<T : Any>(defaultValue, visibility).OptionVisibility<T : Any>sealed hierarchy:OptionVisibility.Visible: All device-supported options are selectable (default).OptionVisibility.Hidden: Setting is hidden/unavailable in the UI; camera runs withdefaultValue.OptionVisibility.Only(enabledOptions): Whitelists specific options in the UI (minimum 2 options; supportsvarargconstruction).OptionVisibility.from(options)/OptionVisibility.from(vararg options): Safe factory functions that automatically fall back toHiddenwhen fewer than 2 options are provided, preventing runtime crash traps during dynamic option resolution.defaultValuemust be included inOptionVisibility.Only.flashModemust default toOFFwhenHiddenand must includeOFFwhen restricted.JPEG_ULTRA_HDR) and HDR video (HLG10) are supported as defaults underHidden(hardware fallbacks to SDR are handled gracefully at runtime if unsupported by the active camera).CameraFeaturePolicy.toCameraAppSettings(defaultSettings)to map overrides cleanly over baseline settings.Settings Storage & Data Layer (
data:settings,core:settings:datastore-prefs):LocalSettingsRepositoryandPrefsDataStoreSettingsDataSourceto enforceCameraFeaturePolicy:enforceRestrictions(storedSetting, settingConfig)across all settings (captureMode,aspectRatio,flashMode,imageFormat,dynamicRange) to preserve valid user-selected preferences underOptionVisibility.Onlyrather than unconditionally overwriting them withdefaultValue.Camera System Wiring (
data:camera):CameraFeaturePolicyintoCameraXCameraSystemRepository.CameraFeaturePolicydefaults during lazy camera initialization before use cases bind.UI State & Adapters (
ui:uistateadapter:capture):optionVisibilityacross all option adapters.OptionVisibilitypolicies into:CaptureModeUiStateAdapter: Respects hidden capture mode, hides/disables toggle buttons or quick-settings rows appropriately, and provides clear disabled rationales. Documented the binary quick-toggle contract forCaptureModeToggleUiState(requiring 2 valid selectable states; directing custom layouts toCaptureModeUiStatefor disabled reasons).FlashModeUiStateAdapter: Filters selectable flash modes or marks asUnavailablewhen hidden or unsupported.AspectRatioUiStateAdapter: Restricts selectable aspect ratios and falls back deterministically to 3:4 if the currently stored selection is restricted.HdrUiStateAdapter: Disables HDR options when dynamic range or image format are restricted. Fixed an issue where Low Light Boost disabled all HDR options instead of keeping "Off" selectable.CaptureUiStateAdapter: WiresCameraFeaturePolicyinto compound UI state generation withcameraFeaturePolicy: CameraFeaturePolicy? = nulldefault parameter.Viewfinder & Quick Settings UI (
feature:preview):quickSettingsState.value is QuickSettingsUiState.AvailableinisQuickSettingsVisiblewithinPreviewScreen.ktso that the drop-down toggle button (ToggleQuickSettingsButton) is hidden whenever quick settings isUnavailable.Dependency Injection & App Integration (
app):CameraFeaturePolicyviaAppModule.providesCameraFeaturePolicy().@Volatile @VisibleForTesting var testCameraFeaturePolicy: CameraFeaturePolicy?to enable isolated, deterministic device test overrides.Testing:
:core:settings: Comprehensive validation ofCameraFeaturePolicy,SettingConfig, andOptionVisibilityedge cases inCameraFeaturePolicyTest.:data:camera: Verified lazy initialization and default overrides inCameraXCameraSystemRepositoryTest.:data:settings: Validated preference persistence and restriction enforcement inLocalSettingsRepositoryTest.:ui:uistateadapter:capture: Tested UI state adaptation, visibility restrictions, and fallback behavior acrossCaptureModeUiStateAdapterTest(including concurrent camera dual & HDR conflict scenarios),FlashModeUiStateAdapterTest,AspectRatioUiStateAdapterTest,HdrUiStateAdapterTest, andCaptureUiStateAdapterTest.:feature:preview: Verified ViewModel integration withCameraFeaturePolicyinPreviewViewModelTest.app):CameraFeaturePolicyconfigurations:CaptureModeFeaturePolicyDeviceTest(including photo and video capture execution)FlashModeFeaturePolicyDeviceTest(including graceful fallback on devices without flash units)AspectRatioFeaturePolicyDeviceTestHdrFeaturePolicyDeviceTestCaptureModeSettingsTest.hdr_supports_video_only()usingtestCameraFeaturePolicyfor deterministic behavior across dual-HDR and single-HDR devices.Usage Example
Limitations & Future Work
audioEnabledconfiguration is deferred to a follow-up PR, pending visual UX design.onNavigateToSettingsto determine whether the toggle button should navigate directly to full settings or remain hidden.