commit 99b0d82c4a92a28d894d4106cb03b8bc514b9313 parent 9bf160e94bce630932e2f9a906c14eda8556da78 Author: Bastian Gruber <foreach@me.com> Date: Fri, 9 Jan 2026 20:04:18 +0000 Bug 1988163 - Split Studies into Feature Studies and Improvmenets r=beth,android-reviewers,android-l10n-reviewers,flod,twhite Differential Revision: https://phabricator.services.mozilla.com/D274420 Diffstat:
14 files changed, 126 insertions(+), 13 deletions(-)
diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDataCollectionRobot.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDataCollectionRobot.kt @@ -58,7 +58,7 @@ class SettingsSubMenuDataCollectionRobot { itemWithDescription("Learn more about technical data Links available"), // Studies section itemContainingText(getStringResource(R.string.studies_data_category)), - itemContainingText(getStringResource(R.string.studies_title)), + itemContainingText(getStringResource(R.string.studies_title_2)), itemContainingText(studiesSummary), // Usage data section itemContainingText(getStringResource(R.string.usage_data_category)), @@ -139,7 +139,7 @@ class SettingsSubMenuDataCollectionRobot { fun clickStudiesOption() { Log.i(TAG, "clickStudiesOption: Trying to click the \"Studies\" option") - itemContainingText(getStringResource(R.string.studies_title)).click() + itemContainingText(getStringResource(R.string.studies_title_2)).click() Log.i(TAG, "clickStudiesOption: Clicked the \"Studies\" option") } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/RemoteImprovementsFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/RemoteImprovementsFragment.kt @@ -0,0 +1,52 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.settings + +import android.os.Bundle +import androidx.preference.Preference +import androidx.preference.PreferenceFragmentCompat +import androidx.preference.SwitchPreference +import org.mozilla.fenix.R +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.settings +import org.mozilla.fenix.ext.showToolbar + +/** + * Lets the user customize remote improvements (rollouts) settings. + */ +class RemoteImprovementsFragment : PreferenceFragmentCompat() { + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.remote_improvements_preferences, rootKey) + + requirePreference<SwitchPreference>(R.string.pref_key_rollouts).apply { + isChecked = context.settings().isRolloutsEnabled + onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> + val enabled = newValue as? Boolean ?: false + context.settings().isRolloutsEnabled = enabled + context.components.nimbus.sdk.rolloutParticipation = enabled + true + } + } + + requirePreference<Preference>(R.string.pref_key_rollouts_learn_more).apply { + onPreferenceClickListener = Preference.OnPreferenceClickListener { + SupportUtils.launchSandboxCustomTab( + context = requireContext(), + url = SupportUtils.getSumoURLForTopic( + context = requireContext(), + topic = SupportUtils.SumoTopic.REMOTE_IMPROVEMENTS, + ), + ) + true + } + } + } + + override fun onResume() { + super.onResume() + showToolbar(getString(R.string.preferences_remote_improvements)) + } +} diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -480,6 +480,10 @@ class SettingsFragment : PreferenceFragmentCompat() { SettingsFragmentDirections.actionSettingsFragmentToLinkSharingFragment() } + resources.getString(R.string.pref_key_remote_improvements) -> { + SettingsFragmentDirections.actionSettingsFragmentToRemoteImprovementsFragment() + } + resources.getString(R.string.pref_key_open_links_in_apps) -> { SettingsFragmentDirections.actionSettingsFragmentToOpenLinksInAppsFragment() } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt @@ -42,6 +42,7 @@ object SupportUtils { TRACKING_PROTECTION("tracking-protection-firefox-android"), TOTAL_COOKIE_PROTECTION("enhanced-tracking-protection-android"), OPT_OUT_STUDIES("how-opt-out-studies-firefox-android"), + REMOTE_IMPROVEMENTS("remote-improvements"), SEND_TABS("send-tab-preview"), SET_AS_DEFAULT_BROWSER("make-firefox-default-browser-android"), SEARCH_SUGGESTION("how-search-firefox-preview"), diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/datachoices/DataChoicesMiddleware.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/datachoices/DataChoicesMiddleware.kt @@ -104,17 +104,13 @@ internal class DataChoicesMiddleware( metrics.start(MetricServiceType.Data) if (!settings.hasUserDisabledExperimentation) { settings.isExperimentationEnabled = true + nimbusSdk.experimentParticipation = true } - // Use separate participation flags for experiments and rollouts - nimbusSdk.experimentParticipation = true - nimbusSdk.rolloutParticipation = true engine.notifyTelemetryPrefChanged(true) } else { metrics.stop(MetricServiceType.Data) settings.isExperimentationEnabled = false - // Use separate participation flags for experiments and rollouts nimbusSdk.experimentParticipation = false - nimbusSdk.rolloutParticipation = false engine.notifyTelemetryPrefChanged(false) } // Reset experiment identifiers on both opt-in and opt-out; it's likely diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/datachoices/DataChoicesScreen.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/datachoices/DataChoicesScreen.kt @@ -271,7 +271,7 @@ private fun TogglePreferenceSection( } /** - * Composable section that displays the user’s participation status in studies or experiments. + * Composable section that displays the user's participation status in studies or experiments. * * @param studiesEnabled Whether the user is currently enrolled in studies. * Affects the summary text shown in the section. @@ -296,7 +296,7 @@ private fun StudiesSection( ) TextListItem( - label = stringResource(R.string.studies_title), + label = stringResource(R.string.studies_title_2), description = stringResource(if (studiesEnabled) R.string.studies_on else R.string.studies_off), enabled = sectionEnabled, onClick = onClick, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/studies/StudiesView.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/studies/StudiesView.kt @@ -65,7 +65,6 @@ class StudiesView( // Use experimentParticipation for studies-specific settings experiments.experimentParticipation = isChecked - experiments.rolloutParticipation = isChecked } bindDescription() @@ -95,7 +94,7 @@ class StudiesView( @VisibleForTesting internal fun bindDescription() { val sumoUrl = SupportUtils.getGenericSumoURLForTopic(OPT_OUT_STUDIES) - val description = context.getString(R.string.studies_description_3) + val description = context.getString(R.string.studies_description_4) val learnMore = context.getString(R.string.studies_learn_more) val rawText = "$description <a href=\"$sumoUrl\">$learnMore</a>" val text = HtmlCompat.fromHtml(rawText, HtmlCompat.FROM_HTML_MODE_COMPACT) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -709,6 +709,16 @@ class Settings( default = false, ) + /** + * Controls whether the user is opted into rollouts (remote improvements). + * Rollouts are completely decoupled from telemetry and experiments, so users + * can receive feature updates regardless of their telemetry or experiment settings. + */ + var isRolloutsEnabled by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_rollouts), + default = appContext.components.nimbus.sdk.rolloutParticipation, + ) + var isOverrideTPPopupsForPerformanceTest = false // We do not use `booleanPreference` because we only want the "read" part of this setting to be diff --git a/mobile/android/fenix/app/src/main/res/navigation/nav_graph.xml b/mobile/android/fenix/app/src/main/res/navigation/nav_graph.xml @@ -770,6 +770,13 @@ app:popEnterAnim="@anim/slide_in_left" app:popExitAnim="@anim/slide_out_right" /> <action + android:id="@+id/action_settingsFragment_to_remoteImprovementsFragment" + app:destination="@id/remoteImprovementsFragment" + app:enterAnim="@anim/slide_in_right" + app:exitAnim="@anim/slide_out_left" + app:popEnterAnim="@anim/slide_in_left" + app:popExitAnim="@anim/slide_out_right" /> + <action android:id="@+id/action_settingsFragment_to_tabsSettingsFragment" app:destination="@id/tabsSettingsFragment" app:enterAnim="@anim/slide_in_right" @@ -1075,6 +1082,9 @@ android:id="@+id/linkSharingFragment" android:name="org.mozilla.fenix.settings.LinkSharingFragment" /> <fragment + android:id="@+id/remoteImprovementsFragment" + android:name="org.mozilla.fenix.settings.RemoteImprovementsFragment" /> + <fragment android:id="@+id/deleteBrowsingDataFragment" android:name="org.mozilla.fenix.settings.deletebrowsingdata.DeleteBrowsingDataFragment" android:label="@string/preferences_delete_browsing_data" diff --git a/mobile/android/fenix/app/src/main/res/values/preference_keys.xml b/mobile/android/fenix/app/src/main/res/values/preference_keys.xml @@ -61,8 +61,11 @@ <string name="pref_key_private_browsing" translatable="false">pref_key_private_browsing</string> <string name="pref_key_leakcanary" translatable="false">pref_key_leakcanary</string> <string name="pref_key_remote_debugging" translatable="false">pref_key_remote_debugging</string> + <string name="pref_key_remote_improvements" translatable="false">pref_key_remote_improvements</string> <string name="pref_key_crash_reporting_choice" translatable="false">pref_key_crash_reporting_choice</string> <string name="pref_key_experimentation_v2" translatable="false">pref_key_experimentation_v2</string> + <string name="pref_key_rollouts" translatable="false">pref_key_rollouts</string> + <string name="pref_key_rollouts_learn_more" translatable="false">pref_key_rollouts_learn_more</string> <string name="pref_key_user_disabled_experimentation" translatable="false">pref_key_user_disabled_experimentation</string> <string name="pref_key_private_mode_opened" translatable="false">pref_key_private_mode_opened</string> <string name="pref_key_open_in_app_opened" translatable="false">pref_key_open_in_app_opened</string> diff --git a/mobile/android/fenix/app/src/main/res/values/strings.xml b/mobile/android/fenix/app/src/main/res/values/strings.xml @@ -1394,12 +1394,26 @@ <!-- Title of the active section on the studies list --> <string name="studies_active">Active</string> <!-- Description for studies --> - <string name="studies_description_3">Try out features and ideas before they’re released to everyone.</string> + <string name="studies_description_3" moz:removedIn="148" tools:ignore="UnusedResources">Try out features and ideas before they’re released to everyone.</string> + <!-- Description for studies. Note: The word "Firefox" should NOT be translated --> + <string name="studies_description_4" tools:ignore="BrandUsage">Firefox randomly selects users to test features, which improves quality for everyone.</string> <!-- Title of the Studies data preference --> - <string name="studies_title">Install and run studies</string> + <string name="studies_title" moz:removedIn="148" tools:ignore="UnusedResources">Install and run studies</string> + <!-- Title of the Studies data preference --> + <string name="studies_title_2">Allow feature studies</string> <!-- Learn more link for studies, links to an article for more information about studies. --> <string name="studies_learn_more">Learn more</string> + <!-- Remote Improvements (Rollouts) --> + <!-- Title of the Remote Improvements (rollouts) data preference --> + <string name="remote_improvements_title">Allow remote improvements</string> + <!-- Description for remote improvements. Note: The word "Firefox" should NOT be translated --> + <string name="remote_improvements_description" tools:ignore="BrandUsage">Firefox will improve features, performance, and stability between updates. Changes applied remotely.</string> + <!-- Learn more link for remote improvements, links to an article for more information about rollouts. --> + <string name="remote_improvements_learn_more">Learn more</string> + <!-- Title for remote improvements preference in Advanced settings --> + <string name="preferences_remote_improvements">Remote improvements</string> + <!-- Sessions --> <!-- Title for the list of tabs in the current normal session used by a11y services The %1$s will be replaced by the number of opened normal tabs --> diff --git a/mobile/android/fenix/app/src/main/res/xml/preferences.xml b/mobile/android/fenix/app/src/main/res/xml/preferences.xml @@ -195,6 +195,11 @@ app:iconSpaceReserved="false" app:isPreferenceVisible="@bool/IS_DEBUG" /> + <androidx.preference.Preference + android:key="@string/pref_key_remote_improvements" + android:title="@string/preferences_remote_improvements" + app:iconSpaceReserved="false" /> + <androidx.preference.SwitchPreference android:key="@string/pref_key_remote_debugging" android:title="@string/preferences_remote_debugging" diff --git a/mobile/android/fenix/app/src/main/res/xml/remote_improvements_preferences.xml b/mobile/android/fenix/app/src/main/res/xml/remote_improvements_preferences.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<androidx.preference.PreferenceScreen + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + <SwitchPreference + android:defaultValue="true" + android:key="@string/pref_key_rollouts" + android:title="@string/remote_improvements_title" + android:summary="@string/remote_improvements_description" + app:iconSpaceReserved="false" /> + <Preference + android:key="@string/pref_key_rollouts_learn_more" + android:title="@string/remote_improvements_learn_more" + app:iconSpaceReserved="false" /> +</androidx.preference.PreferenceScreen> diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/FenixApplicationTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/FenixApplicationTest.kt @@ -81,6 +81,7 @@ class FenixApplicationTest { browserStore = BrowserStore() every { testContext.components.core } returns mockk(relaxed = true) + every { testContext.components.nimbus } returns mockk(relaxed = true) every { testContext.components.distributionIdManager } returns DistributionIdManager( packageManager = testContext.packageManagerWrapper, browserStoreProvider = DefaultDistributionBrowserStoreProvider(browserStore),