closes #23381: add telemetry for wallpapers feature

This commit is contained in:
Matt Tighe 2022-01-21 14:53:16 -08:00 committed by mergify[bot]
parent 4c324abfb2
commit eed42ee96b
11 changed files with 282 additions and 3 deletions

View File

@ -6954,3 +6954,66 @@ search_terms:
notification_emails:
- android-probes@mozilla.com
expires: "2022-12-01"
wallpapers:
discovered_wallpaper_feature:
type: boolean
description: |
Whether or not the user has discovered the wallpaper feature.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/23381
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/23382
notification_emails:
- android-probes@mozilla.com
data_sensitivity:
- interaction
expires: "2023-05-01"
new_wallpaper_applied:
type: labeled_counter
description: |
How many and which type of wallpapers were applied.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/23381
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/23382
notification_emails:
- android-probes@mozilla.com
data_sensitivity:
- interaction
expires: "2023-05-01"
selected_wallpaper:
type: event
description: |
Records the wallpaper that is active at session start.
extra_keys:
name:
description: The name of the selected wallpaper
type: string
is_themed:
description: Whether the selected wallpaper is part of a theme.
type: boolean
bugs:
- https://github.com/mozilla-mobile/fenix/issues/23381
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/23382
notification_emails:
- android-probes@mozilla.com
data_sensitivity:
- interaction
expires: "2023-05-01"
wallpaper_reset_to_default:
type: event
description: |
The user has reset their wallpaper back to the default background.
This means the default is active on startup, and has changed since the
previous session.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/23381
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/23382
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-05-01"

View File

@ -145,7 +145,7 @@ class Components(private val context: Context) {
}
val wallpaperManager by lazyMonitored {
WallpaperManager(settings, WallpapersAssetsStorage(context))
WallpaperManager(settings, WallpapersAssetsStorage(context), analytics.metrics)
}
val analytics by lazyMonitored { Analytics(context) }

View File

@ -676,6 +676,13 @@ sealed class Event {
sealed class Search
sealed class Wallpaper : Event() {
object DiscoveredFeature : Wallpaper()
data class NewWallpaperApplied(val wallpaper: org.mozilla.fenix.wallpapers.Wallpaper) : Wallpaper()
data class WallpaperSelected(val wallpaper: org.mozilla.fenix.wallpapers.Wallpaper) : Wallpaper()
object WallpaperResetToDefault : Wallpaper()
}
internal open val extras: Map<*, String>?
get() = null
}

View File

@ -58,6 +58,7 @@ import org.mozilla.fenix.GleanMetrics.ToolbarSettings
import org.mozilla.fenix.GleanMetrics.TopSites
import org.mozilla.fenix.GleanMetrics.TrackingProtection
import org.mozilla.fenix.GleanMetrics.VoiceSearch
import org.mozilla.fenix.GleanMetrics.Wallpapers
import org.mozilla.fenix.ext.components
private class EventWrapper<T : Enum<T>>(
@ -907,6 +908,25 @@ private val Event.wrapper: EventWrapper<*>?
is Event.JumpBackInGroupTapped -> EventWrapper<NoExtraKeys>(
{ SearchTerms.jumpBackInGroupTapped.record(it) }
)
is Event.Wallpaper.DiscoveredFeature -> EventWrapper<NoExtraKeys>(
{ Wallpapers.discoveredWallpaperFeature.set(true) }
)
is Event.Wallpaper.NewWallpaperApplied -> EventWrapper<NoExtraKeys>(
{ Wallpapers.newWallpaperApplied[this.wallpaper.name].add() }
)
is Event.Wallpaper.WallpaperSelected -> EventWrapper<NoExtraKeys>(
{
Wallpapers.selectedWallpaper.record(
Wallpapers.SelectedWallpaperExtra(
name = this.wallpaper.name,
isThemed = this.wallpaper.isThemed,
),
)
},
)
Event.Wallpaper.WallpaperResetToDefault -> EventWrapper<NoExtraKeys>(
{ Wallpapers.wallpaperResetToDefault.record() }
)
// Don't record other events in Glean:
is Event.AddBookmark -> null

View File

@ -767,6 +767,7 @@ class HomeFragment : Fragment() {
if (shouldEnableWallpaper() && context.settings().wallpapersSwitchedByLogoTap) {
binding.wordmark.setOnClickListener {
val manager = requireComponents.wallpaperManager
manager.recordDiscoveredMetric()
manager.updateWallpaper(
wallpaperContainer = binding.homeLayout,
newWallpaper = manager.switchToNextWallpaper()

View File

@ -36,6 +36,7 @@ class WallpaperSettingsFragment : Fragment() {
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
wallpaperManager.recordDiscoveredMetric()
return ComposeView(requireContext()).apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {

View File

@ -166,6 +166,11 @@ class Settings(private val appContext: Context) : PreferencesHolder {
default = ""
)
var previousWallpaper by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_previous_wallpaper),
default = WallpaperManager.defaultWallpaper.name
)
var currentWallpaper by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_current_wallpaper),
default = WallpaperManager.defaultWallpaper.name
@ -176,6 +181,11 @@ class Settings(private val appContext: Context) : PreferencesHolder {
default = true
)
var wallpapersDiscovered by booleanPreference(
appContext.getPreferenceKey(R.string.pref_key_wallpapers_discovered),
default = false
)
var openLinksInAPrivateTab by booleanPreference(
appContext.getPreferenceKey(R.string.pref_key_open_links_in_a_private_tab),
default = false

View File

@ -10,10 +10,12 @@ package org.mozilla.fenix.wallpapers
* @property portraitPath A file path for the portrait version of this wallpaper.
* @property landscapePath A file path for the landscape version of this wallpaper.
* @property isDark Indicates if the most predominant color on the wallpaper is dark.
* @property isThemed Whether the wallpaper belongs to a themed collection.
*/
data class Wallpaper(
val name: String,
val portraitPath: String,
val landscapePath: String,
val isDark: Boolean
val isDark: Boolean,
val isThemed: Boolean = false,
)

View File

@ -14,15 +14,19 @@ import androidx.appcompat.app.AppCompatDelegate
import mozilla.components.support.base.log.logger.Logger
import mozilla.components.support.ktx.android.content.getColorFromAttr
import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.ext.asActivity
import org.mozilla.fenix.utils.Settings
/**
* Provides access to available wallpapers and manages their states.
*/
@Suppress("TooManyFunctions")
class WallpaperManager(
private val settings: Settings,
private val wallpaperStorage: WallpaperStorage
private val wallpaperStorage: WallpaperStorage,
private val metrics: MetricController,
) {
val logger = Logger("WallpaperManager")
var availableWallpapers: List<Wallpaper> = loadWallpapers()
@ -30,6 +34,7 @@ class WallpaperManager(
var currentWallpaper: Wallpaper = getCurrentWallpaperFromSettings()
set(value) {
settings.previousWallpaper = currentWallpaper.name
settings.currentWallpaper = value.name
field = value
}
@ -50,6 +55,7 @@ class WallpaperManager(
currentWallpaper = newWallpaper
adjustTheme(wallpaperContainer.context)
recordWallpaperAppliedMetric(newWallpaper)
}
private fun adjustTheme(context: Context) {
@ -107,6 +113,8 @@ class WallpaperManager(
defaultWallpaper
} else {
availableWallpapers.find { it.name == currentWallpaper } ?: defaultWallpaper
}.also {
recordSelectionMetrics(it)
}
}
@ -134,6 +142,28 @@ class WallpaperManager(
}
}
fun recordDiscoveredMetric() {
val hasSentMetric = settings.wallpapersDiscovered
if (!hasSentMetric) {
metrics.track(Event.Wallpaper.DiscoveredFeature)
settings.wallpapersDiscovered = true
}
}
private fun recordWallpaperAppliedMetric(appliedWallpaper: Wallpaper) {
metrics.track(Event.Wallpaper.NewWallpaperApplied(appliedWallpaper))
}
private fun recordSelectionMetrics(currentWallpaper: Wallpaper) {
val previousWallpaperName = settings.previousWallpaper
if (previousWallpaperName != defaultWallpaper.name && currentWallpaper == defaultWallpaper) {
metrics.track(Event.Wallpaper.WallpaperResetToDefault)
// This metric will continue to be reported unless the previous wallpaper is reset
settings.previousWallpaper = currentWallpaper.name
}
metrics.track(Event.Wallpaper.WallpaperSelected(currentWallpaper))
}
companion object {
const val DEFAULT_RESOURCE = R.attr.homeBackground
val defaultWallpaper = Wallpaper(

View File

@ -189,8 +189,10 @@
<!-- Wallpaper Settings -->
<string name="pref_key_wallpapers" translatable="false">pref_key_wallpapers</string>
<string name="pref_key_previous_wallpaper" translatable="false">pref_key_previous_wallpaper</string>
<string name="pref_key_current_wallpaper" translatable="false">pref_key_current_wallpaper</string>
<string name="pref_key_wallpapers_switched_by_logo_tap">pref_key_wallpapers_switched_by_logo_tap</string>
<string name="pref_key_wallpapers_discovered" translatable="false">pref_key_wallpapers_discovered</string>
<string name="pref_key_encryption_key_generated" translatable="false">pref_key_encryption_key_generated</string>

View File

@ -0,0 +1,143 @@
package org.mozilla.fenix.wallpapers
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import io.mockk.slot
import io.mockk.verify
import org.junit.Assert.assertEquals
import org.junit.Test
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.utils.Settings
class WallpaperManagerTest {
private val fakeWallpaper = Wallpaper(
name = "fake wallpaper",
portraitPath = "",
landscapePath = "",
isDark = false,
isThemed = false,
)
private val fakeThemedWallpaper = Wallpaper(
name = "fake themed wallpaper",
portraitPath = "",
landscapePath = "",
isDark = false,
isThemed = true,
)
private val fakeWallpapers = listOf(fakeWallpaper, fakeThemedWallpaper)
private val mockSettings: Settings = mockk()
private val mockStorage: WallpaperStorage = mockk {
every { loadAll() } returns fakeWallpapers
}
private val mockMetrics: MetricController = mockk()
@Test
fun `WHEN wallpaper set THEN current wallpaper updated in settings`() {
every { mockMetrics.track(any()) } just runs
val currentCaptureSlot = slot<String>()
val updatedWallpaper = fakeWallpaper
every { mockSettings.currentWallpaper } returns WallpaperManager.defaultWallpaper.name
every { mockSettings.currentWallpaper = capture(currentCaptureSlot) } just runs
every { mockSettings.previousWallpaper } returns WallpaperManager.defaultWallpaper.name
every { mockSettings.previousWallpaper = capture(slot()) } just runs
val wallpaperManager = WallpaperManager(mockSettings, mockStorage, mockMetrics)
wallpaperManager.currentWallpaper = updatedWallpaper
assertEquals(updatedWallpaper.name, currentCaptureSlot.captured)
}
@Test
fun `WHEN wallpaper set THEN current wallpaper saved as previous in settings`() {
every { mockMetrics.track(any()) } just runs
val previousCaptureSlot = slot<String>()
val currentWallpaper = fakeWallpaper
every { mockSettings.currentWallpaper } returns currentWallpaper.name
every { mockSettings.currentWallpaper = capture(slot()) } just runs
every { mockSettings.previousWallpaper } returns WallpaperManager.defaultWallpaper.name
every { mockSettings.previousWallpaper = capture(previousCaptureSlot) } just runs
val wallpaperManager = WallpaperManager(mockSettings, mockStorage, mockMetrics)
wallpaperManager.currentWallpaper = WallpaperManager.defaultWallpaper
assertEquals(currentWallpaper.name, previousCaptureSlot.captured)
}
@Test
fun `WHEN wallpaper is initially fetched from settings THEN selection metric reported`() {
val defaultWallpaper = WallpaperManager.defaultWallpaper
every { mockSettings.previousWallpaper } returns defaultWallpaper.name
every { mockSettings.currentWallpaper } returns defaultWallpaper.name
every { mockMetrics.track(any()) } just runs
WallpaperManager(mockSettings, mockStorage, mockMetrics)
verify { mockMetrics.track(Event.Wallpaper.WallpaperSelected(defaultWallpaper)) }
}
@Test
fun `GIVEN previous wallpaper was not default WHEN current wallpaper is loaded as default THEN selection metric reported and previous reset`() {
val defaultWallpaper = WallpaperManager.defaultWallpaper
val previousSlot = slot<String>()
every { mockSettings.previousWallpaper } returns fakeWallpaper.name
every { mockSettings.previousWallpaper = capture(previousSlot) } just runs
every { mockSettings.currentWallpaper } returns defaultWallpaper.name
every { mockMetrics.track(any()) } just runs
WallpaperManager(mockSettings, mockStorage, mockMetrics)
assertEquals(defaultWallpaper.name, previousSlot.captured)
verify { mockMetrics.track(Event.Wallpaper.WallpaperResetToDefault) }
verify { mockMetrics.track(Event.Wallpaper.WallpaperSelected(defaultWallpaper)) }
}
@Test
fun `WHEN wallpaper updated THEN wallpaper applied metric recorded`() {
val defaultWallpaper = WallpaperManager.defaultWallpaper
every { mockSettings.previousWallpaper } returns defaultWallpaper.name
every { mockSettings.previousWallpaper = capture(slot()) } just runs
every { mockSettings.currentWallpaper } returns defaultWallpaper.name
every { mockSettings.currentWallpaper = capture(slot()) } just runs
every { mockMetrics.track(any()) } just runs
val manager = WallpaperManager(mockSettings, mockStorage, mockMetrics)
manager.updateWallpaper(mockk(relaxed = true), defaultWallpaper)
verify { mockMetrics.track(Event.Wallpaper.NewWallpaperApplied(defaultWallpaper)) }
}
@Test
fun `WHEN wallpaper discovered metric not previously recorded WHEN metric record attempted THEN metric sent`() {
every { mockSettings.wallpapersDiscovered } returns false
every { mockSettings.previousWallpaper } returns WallpaperManager.defaultWallpaper.name
every { mockSettings.currentWallpaper } returns WallpaperManager.defaultWallpaper.name
every { mockSettings.wallpapersDiscovered = true } just runs
every { mockMetrics.track(any()) } just runs
val wallpaperManager = WallpaperManager(mockSettings, mockStorage, mockMetrics)
wallpaperManager.recordDiscoveredMetric()
verify { mockMetrics.track(Event.Wallpaper.DiscoveredFeature) }
verify { mockSettings.wallpapersDiscovered = true }
}
@Test
fun `WHEN wallpaper discovered metric previously recorded WHEN metric record attempted THEN metric not sent`() {
every { mockSettings.wallpapersDiscovered } returns true
every { mockSettings.previousWallpaper } returns WallpaperManager.defaultWallpaper.name
every { mockSettings.currentWallpaper } returns WallpaperManager.defaultWallpaper.name
every { mockMetrics.track(any()) } just runs
val wallpaperManager = WallpaperManager(mockSettings, mockStorage, mockMetrics)
wallpaperManager.recordDiscoveredMetric()
verify(exactly = 0) { mockMetrics.track(Event.Wallpaper.DiscoveredFeature) }
}
}