commit 6159ff26750c145723217199b0d8efb4b1a0985d parent 6e92aa7f9db81ab8412ed3355bc1f7d5c9428d91 Author: John Oberhauser <j.git-global@obez.io> Date: Mon, 15 Dec 2025 16:15:17 +0000 Bug 2005646: Enabling Adjust's COPPA mode for Digital Turbine distributions r=android-reviewers,gmalekpour Differential Revision: https://phabricator.services.mozilla.com/D276107 Diffstat:
10 files changed, 146 insertions(+), 24 deletions(-)
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt @@ -280,6 +280,8 @@ open class FenixApplication : LocaleAwareApplication(), Provider { settings().hasMadeMarketingTelemetrySelection, isDailyUsagePingEnabled = settings().isDailyUsagePingEnabled, ) + } else { + components.distributionIdManager.startAdjustIfSkippingConsentScreen() } setupPush() diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt @@ -349,6 +349,7 @@ class Components(private val context: Context) { browserStoreProvider = DefaultDistributionBrowserStoreProvider(core.store), distributionProviderChecker = DefaultDistributionProviderChecker(context), distributionSettings = DefaultDistributionSettings(settings), + metricController = analytics.metrics, ) } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/AdjustMetricsService.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/AdjustMetricsService.kt @@ -94,11 +94,7 @@ class AdjustMetricsService( triggerPing() } - if (Config.channel.isNightlyOrDebug) { - config.setLogLevel(LogLevel.VERBOSE) - } else { - config.setLogLevel(LogLevel.SUPPRESS) - } + config.setLogLevel(LogLevel.SUPPRESS) Adjust.initSdk(config) Adjust.enable() diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/MarketingAttributionService.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/MarketingAttributionService.kt @@ -60,12 +60,7 @@ class MarketingAttributionService(private val context: Context) { val utmParams = UTMParams.parseUTMParameters(installReferrerResponse) distributionIdManager.updateDistributionIdFromUtmParams(utmParams) - - if (distributionIdManager.shouldSkipMarketingConsentScreen()) { - context.components.settings.isMarketingTelemetryEnabled = true - context.components.settings.hasMadeMarketingTelemetrySelection = true - context.components.analytics.metrics.start(MetricServiceType.Marketing) - } + distributionIdManager.startAdjustIfSkippingConsentScreen() } context.settings().shouldShowMarketingOnboarding = diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/distributions/DistributionIdManager.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/distributions/DistributionIdManager.kt @@ -11,6 +11,8 @@ import mozilla.components.support.base.log.logger.Logger import mozilla.components.support.utils.ext.PackageManagerWrapper import org.mozilla.fenix.GleanMetrics.Metrics import org.mozilla.fenix.GleanMetrics.Partnerships +import org.mozilla.fenix.components.metrics.MetricController +import org.mozilla.fenix.components.metrics.MetricServiceType import org.mozilla.fenix.components.metrics.UTMParams import java.io.File import java.util.Locale @@ -41,6 +43,7 @@ private val logger = Logger(DistributionIdManager::class.simpleName) * @param browserStoreProvider used to update and fetch the stored distribution Id * @param distributionProviderChecker used for checking content providers for a distribution provider * @param distributionSettings used to persist and retrieve the distribution ID + * @param metricController a controller used to start Adjust. * @param appPreinstalledOnVivoDevice checks if the vivo preinstalled file exists. * @param isDtTelefonicaInstalled checks if the DT telefonica app is installed on the device * @param isDtUsaInstalled checks if one of the DT USA carrier apps is installed on the device @@ -50,6 +53,7 @@ class DistributionIdManager( private val browserStoreProvider: DistributionBrowserStoreProvider, private val distributionProviderChecker: DistributionProviderChecker, private val distributionSettings: DistributionSettings, + private val metricController: MetricController, private val appPreinstalledOnVivoDevice: () -> Boolean = { wasAppPreinstalledOnVivoDevice() }, private val isDtTelefonicaInstalled: () -> Boolean = { isDtTelefonicaInstalled(packageManager) }, private val isDtUsaInstalled: () -> Boolean = { isDtUsaInstalled(packageManager) }, @@ -117,9 +121,9 @@ class DistributionIdManager( return when (id) { Distribution.DEFAULT -> false Distribution.VIVO_001 -> true - Distribution.DT_001 -> false - Distribution.DT_002 -> false - Distribution.DT_003 -> false + Distribution.DT_001 -> true + Distribution.DT_002 -> true + Distribution.DT_003 -> true Distribution.AURA_001 -> false Distribution.XIAOMI_001 -> false } @@ -144,6 +148,18 @@ class DistributionIdManager( } } + /** + * Sets the proper marketing telemetry preferences and starts Adjust if the + * current distribution is one that should skip the marketing data sharing + * consent screen. + */ + fun startAdjustIfSkippingConsentScreen() { + if (shouldSkipMarketingConsentScreen()) { + distributionSettings.setMarketingTelemetryPreferences() + metricController.start(MetricServiceType.Marketing) + } + } + private fun isDeviceVivo(): Boolean { return Build.MANUFACTURER?.lowercase(Locale.getDefault())?.contains(VIVO_MANUFACTURER) ?: false } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/distributions/DistributionSettings.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/distributions/DistributionSettings.kt @@ -23,6 +23,12 @@ interface DistributionSettings { * @param id A non-null string representing the distribution ID to store. */ fun saveDistributionId(id: String) + + /** + * Sets the marketing telemetry preferences to true. This is required + * for skipping the marketing data sharing consent screen before starting Adjust. + */ + fun setMarketingTelemetryPreferences() } /** @@ -49,4 +55,9 @@ class DefaultDistributionSettings( override fun saveDistributionId(id: String) { settings.distributionId = id } + + override fun setMarketingTelemetryPreferences() { + settings.isMarketingTelemetryEnabled = true + settings.hasMadeMarketingTelemetrySelection = true + } } 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 @@ -36,6 +36,7 @@ import org.mozilla.fenix.GleanMetrics.Preferences import org.mozilla.fenix.GleanMetrics.SearchDefaultEngine import org.mozilla.fenix.GleanMetrics.TabStrip import org.mozilla.fenix.GleanMetrics.TopSites +import org.mozilla.fenix.components.fake.FakeMetricController import org.mozilla.fenix.components.metrics.MozillaProductDetector import org.mozilla.fenix.components.toolbar.ToolbarPosition import org.mozilla.fenix.distributions.DefaultDistributionBrowserStoreProvider @@ -69,6 +70,7 @@ class FenixApplicationTest { private val testDistributionSettings = object : DistributionSettings { override fun getDistributionId(): String = "" override fun saveDistributionId(id: String) = Unit + override fun setMarketingTelemetryPreferences() = Unit } @Before @@ -84,6 +86,7 @@ class FenixApplicationTest { browserStoreProvider = DefaultDistributionBrowserStoreProvider(browserStore), distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), ) } diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/metrics/MarketingAttributionServiceTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/metrics/MarketingAttributionServiceTest.kt @@ -11,6 +11,7 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test import org.junit.runner.RunWith +import org.mozilla.fenix.components.fake.FakeMetricController import org.mozilla.fenix.distributions.DistributionBrowserStoreProvider import org.mozilla.fenix.distributions.DistributionIdManager import org.mozilla.fenix.distributions.DistributionProviderChecker @@ -41,6 +42,8 @@ internal class MarketingAttributionServiceTest { override fun saveDistributionId(id: String) { savedId = id } + + override fun setMarketingTelemetryPreferences() = Unit } val distributionIdManager = DistributionIdManager( @@ -48,6 +51,7 @@ internal class MarketingAttributionServiceTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), appPreinstalledOnVivoDevice = { true }, ) @@ -81,19 +85,19 @@ internal class MarketingAttributionServiceTest { fun `GIVEN a partnership distribution WHEN we should skip the marketing screen THEN we skip it`() { distributionIdManager.setDistribution(DistributionIdManager.Distribution.VIVO_001) assertFalse(MarketingAttributionService.shouldShowMarketingOnboarding(null, distributionIdManager)) - } - @Test - fun `GIVEN a partnership distribution WHEN we should not skip the marketing screen THEN we do not skip it`() { distributionIdManager.setDistribution(DistributionIdManager.Distribution.DT_001) - assertTrue(MarketingAttributionService.shouldShowMarketingOnboarding(null, distributionIdManager)) + assertFalse(MarketingAttributionService.shouldShowMarketingOnboarding(null, distributionIdManager)) distributionIdManager.setDistribution(DistributionIdManager.Distribution.DT_002) - assertTrue(MarketingAttributionService.shouldShowMarketingOnboarding(null, distributionIdManager)) + assertFalse(MarketingAttributionService.shouldShowMarketingOnboarding(null, distributionIdManager)) distributionIdManager.setDistribution(DistributionIdManager.Distribution.DT_003) - assertTrue(MarketingAttributionService.shouldShowMarketingOnboarding(null, distributionIdManager)) + assertFalse(MarketingAttributionService.shouldShowMarketingOnboarding(null, distributionIdManager)) + } + @Test + fun `GIVEN a partnership distribution WHEN we should not skip the marketing screen THEN we do not skip it`() { distributionIdManager.setDistribution(DistributionIdManager.Distribution.AURA_001) assertTrue(MarketingAttributionService.shouldShowMarketingOnboarding(null, distributionIdManager)) diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/distributions/DistributionIdManagerTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/distributions/DistributionIdManagerTest.kt @@ -10,9 +10,12 @@ import org.junit.After import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith +import org.mozilla.fenix.components.fake.FakeMetricController +import org.mozilla.fenix.components.metrics.MetricServiceType import org.mozilla.fenix.components.metrics.UTMParams import org.robolectric.RobolectricTestRunner import org.robolectric.shadows.ShadowBuild +import kotlin.collections.listOf @RunWith(RobolectricTestRunner::class) class DistributionIdManagerTest { @@ -40,6 +43,8 @@ class DistributionIdManagerTest { override fun saveDistributionId(id: String) { savedId = id } + + override fun setMarketingTelemetryPreferences() = Unit } @After @@ -58,6 +63,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), appPreinstalledOnVivoDevice = { true }, ) @@ -76,6 +82,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), appPreinstalledOnVivoDevice = { true }, ) @@ -91,6 +98,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), appPreinstalledOnVivoDevice = { false }, ) @@ -109,6 +117,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), ) val distributionId = subject.getDistributionId() @@ -123,6 +132,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), isDtTelefonicaInstalled = { true }, ) @@ -139,6 +149,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), isDtTelefonicaInstalled = { true }, ) @@ -155,6 +166,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), isDtTelefonicaInstalled = { false }, ) @@ -171,6 +183,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), isDtTelefonicaInstalled = { true }, ) @@ -187,6 +200,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), isDtTelefonicaInstalled = { false }, ) @@ -203,6 +217,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), ) subject.setDistribution(DistributionIdManager.Distribution.DEFAULT) @@ -228,12 +243,13 @@ class DistributionIdManagerTest { } @Test - fun `WHEN the distribution is vivo THEN the marketing screen should be skipped`() { + fun `WHEN the distribution should skip the marketing screen THEN the marketing screen is skipped`() { val subject = DistributionIdManager( packageManager = testContext.packageManagerWrapper, testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), ) subject.setDistribution(DistributionIdManager.Distribution.DEFAULT) @@ -243,13 +259,13 @@ class DistributionIdManagerTest { assertEquals(true, subject.shouldSkipMarketingConsentScreen()) subject.setDistribution(DistributionIdManager.Distribution.DT_001) - assertEquals(false, subject.shouldSkipMarketingConsentScreen()) + assertEquals(true, subject.shouldSkipMarketingConsentScreen()) subject.setDistribution(DistributionIdManager.Distribution.DT_002) - assertEquals(false, subject.shouldSkipMarketingConsentScreen()) + assertEquals(true, subject.shouldSkipMarketingConsentScreen()) subject.setDistribution(DistributionIdManager.Distribution.DT_003) - assertEquals(false, subject.shouldSkipMarketingConsentScreen()) + assertEquals(true, subject.shouldSkipMarketingConsentScreen()) subject.setDistribution(DistributionIdManager.Distribution.AURA_001) assertEquals(false, subject.shouldSkipMarketingConsentScreen()) @@ -265,6 +281,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), ) providerValue = "aura" @@ -280,6 +297,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), isDtUsaInstalled = { true }, ) @@ -296,6 +314,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), isDtUsaInstalled = { true }, ) @@ -312,6 +331,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), ) providerValue = "digital_turbine" @@ -327,6 +347,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), ) subject.updateDistributionIdFromUtmParams( @@ -351,6 +372,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), ) subject.updateDistributionIdFromUtmParams( @@ -375,6 +397,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), ) subject.updateDistributionIdFromUtmParams( @@ -399,6 +422,7 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), ) testDistributionSettings.saveDistributionId("vivo-001") @@ -415,10 +439,31 @@ class DistributionIdManagerTest { testBrowserStoreProvider, distributionProviderChecker = testDistributionProviderChecker, distributionSettings = testDistributionSettings, + metricController = FakeMetricController(), ) val distributionId = subject.getDistributionId() assertEquals("Mozilla", distributionId) } + + @Test + fun `GIVEN the marketing screen should be skipped WHEN we try to start marketing metrics services THEN the services are started`() { + val metricsController = FakeMetricController() + + val subject = DistributionIdManager( + packageManager = testContext.packageManagerWrapper, + testBrowserStoreProvider, + distributionProviderChecker = testDistributionProviderChecker, + distributionSettings = testDistributionSettings, + metricController = metricsController, + ) + subject.setDistribution(DistributionIdManager.Distribution.VIVO_001) + subject.startAdjustIfSkippingConsentScreen() + + assertEquals( + listOf(MetricServiceType.Marketing), + metricsController.startedServiceTypes, + ) + } } diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/distributions/DistributionSettingsTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/distributions/DistributionSettingsTest.kt @@ -0,0 +1,49 @@ +/* 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.distributions + +import mozilla.components.support.test.robolectric.testContext +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.utils.Settings +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class DistributionSettingsTest { + + lateinit var subject: DistributionSettings + + lateinit var settings: Settings + + @Before + fun setup() { + settings = Settings(testContext) + subject = DefaultDistributionSettings( + settings = settings, + ) + } + + @Test + fun `WHEN getDistributionId is called THEN the saved distributionID is returned`() { + settings.distributionId = "test" + assertEquals("test", subject.getDistributionId()) + } + + @Test + fun `WHEN the distribution ID is saved THEN it can be retrieved`() { + subject.saveDistributionId("test") + assertEquals("test", subject.getDistributionId()) + } + + @Test + fun `WHEN the marketing telemetry prefs are set THEN they are correct`() { + subject.setMarketingTelemetryPreferences() + assertTrue(settings.isMarketingTelemetryEnabled) + assertTrue(settings.hasMadeMarketingTelemetrySelection) + } +}