Skip to content

Commit 288313a

Browse files
committed
Bug 1921220: move usage profile id into new separate usage reporting service r=android-reviewers,boek
Differential Revision: https://phabricator.services.mozilla.com/D234491
1 parent 6981084 commit 288313a

File tree

7 files changed

+180
-142
lines changed

7 files changed

+180
-142
lines changed

mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Analytics.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import org.mozilla.fenix.ReleaseChannel
2525
import org.mozilla.fenix.components.metrics.AdjustMetricsService
2626
import org.mozilla.fenix.components.metrics.DefaultMetricsStorage
2727
import org.mozilla.fenix.components.metrics.GleanMetricsService
28+
import org.mozilla.fenix.components.metrics.GleanProfileIdPreferenceStore
2829
import org.mozilla.fenix.components.metrics.GleanUsageReportingMetricsService
2930
import org.mozilla.fenix.components.metrics.InstallReferrerMetricsService
3031
import org.mozilla.fenix.components.metrics.MetricController
@@ -150,7 +151,7 @@ class Analytics(
150151
crashReporter = crashReporter,
151152
),
152153
InstallReferrerMetricsService(context),
153-
GleanUsageReportingMetricsService(),
154+
GleanUsageReportingMetricsService(gleanProfileIdStore = GleanProfileIdPreferenceStore(context)),
154155
),
155156
isDataTelemetryEnabled = { context.settings().isTelemetryEnabled },
156157
isMarketingDataTelemetryEnabled = { context.settings().isMarketingTelemetryEnabled },

mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt

Lines changed: 0 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,11 @@
55
package org.mozilla.fenix.components.metrics
66

77
import android.content.Context
8-
import androidx.preference.PreferenceManager
98
import mozilla.components.support.base.log.logger.Logger
109
import mozilla.components.support.utils.RunWhenReadyQueue
1110
import mozilla.telemetry.glean.Glean
1211
import org.mozilla.fenix.GleanMetrics.Pings
13-
import org.mozilla.fenix.GleanMetrics.Usage
14-
import org.mozilla.fenix.R
1512
import org.mozilla.fenix.ext.components
16-
import org.mozilla.fenix.ext.getPreferenceKey
17-
import java.util.UUID
1813

1914
private class EventWrapper<T : Enum<T>>(
2015
private val recorder: ((Map<T, String>?) -> Unit),
@@ -66,8 +61,6 @@ private val Event.wrapper: EventWrapper<*>?
6661
class GleanMetricsService(
6762
private val context: Context,
6863
private val runWhenReadyQueue: RunWhenReadyQueue = context.components.performance.visualCompletenessQueue.queue,
69-
private val gleanProfileId: GleanProfileId = UsageProfileId(),
70-
private val gleanProfileIdStore: GleanProfileIdStore = GleanProfileIdPreferenceStore(context),
7164
) : MetricsService {
7265
override val type = MetricServiceType.Data
7366

@@ -84,8 +77,6 @@ class GleanMetricsService(
8477
if (initialized) return
8578
initialized = true
8679

87-
checkAndSetUsageProfileId()
88-
8980
// The code below doesn't need to execute immediately, so we'll add them to the visual
9081
// completeness task queue to be run later.
9182
runWhenReadyQueue.runIfReadyOrQueue {
@@ -102,7 +93,6 @@ class GleanMetricsService(
10293

10394
override fun stop() {
10495
Glean.setCollectionEnabled(false)
105-
unsetUsageProfileId()
10696
}
10797

10898
override fun track(event: Event) {
@@ -112,96 +102,4 @@ class GleanMetricsService(
112102
override fun shouldTrack(event: Event): Boolean {
113103
return event.wrapper != null
114104
}
115-
116-
private fun checkAndSetUsageProfileId() {
117-
val profileId = gleanProfileIdStore.profileId
118-
if (profileId == null) {
119-
gleanProfileIdStore.profileId = gleanProfileId.generateAndSet().toString()
120-
} else {
121-
gleanProfileId.set(UUID.fromString(profileId))
122-
}
123-
}
124-
125-
private fun unsetUsageProfileId() {
126-
gleanProfileId.unset()
127-
gleanProfileIdStore.clear()
128-
}
129-
}
130-
131-
/**
132-
* An abstraction to represent a profile id as required by Glean.
133-
*/
134-
interface GleanProfileId {
135-
/**
136-
* Create a random UUID and set it in Glean.
137-
*/
138-
fun generateAndSet(): UUID
139-
140-
/**
141-
* Set the given profile id in Glean.
142-
*/
143-
fun set(profileId: UUID)
144-
145-
/**
146-
* Unset the current profile id in Glean.
147-
*/
148-
fun unset()
149-
}
150-
151-
private class UsageProfileId : GleanProfileId {
152-
companion object {
153-
/**
154-
* Glean doesn't have an API to remove a value,
155-
* so we have to use this canary value.
156-
* (would also allow us to notice if we ever accidentally sent data after we shouldn't).
157-
*/
158-
private const val CANARY_VALUE = "beefbeef-beef-beef-beef-beeefbeefbee"
159-
}
160-
161-
override fun generateAndSet(): UUID = Usage.profileId.generateAndSet()
162-
override fun set(profileId: UUID) {
163-
Usage.profileId.set(profileId)
164-
}
165-
166-
override fun unset() {
167-
Usage.profileId.set(UUID.fromString(CANARY_VALUE))
168-
}
169-
}
170-
171-
/**
172-
* An abstraction to represent the storage mechanism within the app for a Glean profile id.
173-
*/
174-
interface GleanProfileIdStore {
175-
/**
176-
* Property allowing access to the profile id which is stored.
177-
*/
178-
var profileId: String?
179-
180-
/**
181-
* Remove the stored profile id.
182-
*/
183-
fun clear()
184-
}
185-
186-
private class GleanProfileIdPreferenceStore(context: Context) : GleanProfileIdStore {
187-
private val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
188-
private val preferenceKey = context.getPreferenceKey(R.string.pref_key_glean_usage_profile_id)
189-
190-
override var profileId: String?
191-
get() = defaultSharedPreferences.getString(
192-
preferenceKey,
193-
null,
194-
)
195-
set(value) {
196-
defaultSharedPreferences.edit()
197-
.putString(
198-
preferenceKey,
199-
value,
200-
).apply()
201-
}
202-
203-
override fun clear() {
204-
defaultSharedPreferences.edit()
205-
.remove(preferenceKey).apply()
206-
}
207105
}

mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/metrics/GleanUsageReportingMetricsService.kt

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,32 @@
44

55
package org.mozilla.fenix.components.metrics
66

7+
import android.content.Context
78
import androidx.lifecycle.LifecycleEventObserver
89
import androidx.lifecycle.LifecycleOwner
910
import androidx.lifecycle.ProcessLifecycleOwner
11+
import androidx.preference.PreferenceManager
1012
import mozilla.components.support.base.log.logger.Logger
13+
import org.mozilla.fenix.GleanMetrics.Usage
14+
import org.mozilla.fenix.R
15+
import org.mozilla.fenix.ext.getPreferenceKey
16+
import java.util.UUID
1117

1218
/**
1319
* Metrics service which encapsulates sending the usage reporting ping.
1420
* @param lifecycleOwner the top level container whose lifecycle is followed by usage data
1521
* @param gleanUsageReportingLifecycleObserver this can be provided to control
1622
* the start / stop sending events for the usage reporting ping
1723
* @param gleanUsageReporting this can be provided to encapsulate interactions with the glean API
24+
* @param gleanProfileId the glean profile id for usage reporting
25+
* @param gleanProfileIdStore the app level storage mechanism for the glean profile id
1826
*/
1927
class GleanUsageReportingMetricsService(
2028
private val lifecycleOwner: LifecycleOwner = ProcessLifecycleOwner.get(),
2129
private val gleanUsageReportingLifecycleObserver: LifecycleEventObserver = GleanUsageReportingLifecycleObserver(),
2230
private val gleanUsageReporting: GleanUsageReportingApi = GleanUsageReporting(),
31+
private val gleanProfileId: GleanProfileId = UsageProfileId(),
32+
private val gleanProfileIdStore: GleanProfileIdStore,
2333
) : MetricsService {
2434

2535
override val type: MetricServiceType = MetricServiceType.UsageReporting
@@ -28,12 +38,14 @@ class GleanUsageReportingMetricsService(
2838
override fun start() {
2939
logger.debug("Start GleanUsageReportingMetricsService")
3040
gleanUsageReporting.setEnabled(true)
41+
checkAndSetUsageProfileId()
3142
lifecycleOwner.lifecycle.addObserver(gleanUsageReportingLifecycleObserver)
3243
}
3344

3445
override fun stop() {
3546
logger.debug("Stop GleanUsageReportingMetricsService")
3647
gleanUsageReporting.setEnabled(false)
48+
unsetUsageProfileId()
3749
lifecycleOwner.lifecycle.removeObserver(gleanUsageReportingLifecycleObserver)
3850
}
3951

@@ -42,4 +54,103 @@ class GleanUsageReportingMetricsService(
4254
}
4355

4456
override fun shouldTrack(event: Event): Boolean = false
57+
58+
private fun checkAndSetUsageProfileId() {
59+
val profileId = gleanProfileIdStore.profileId
60+
if (profileId == null) {
61+
gleanProfileIdStore.profileId = gleanProfileId.generateAndSet().toString()
62+
} else {
63+
gleanProfileId.set(UUID.fromString(profileId))
64+
}
65+
}
66+
67+
private fun unsetUsageProfileId() {
68+
gleanProfileId.unset()
69+
gleanProfileIdStore.clear()
70+
}
71+
}
72+
73+
/**
74+
* An abstraction to represent a profile id as required by Glean.
75+
*/
76+
interface GleanProfileId {
77+
/**
78+
* Create a random UUID and set it in Glean.
79+
*/
80+
fun generateAndSet(): UUID
81+
82+
/**
83+
* Set the given profile id in Glean.
84+
*/
85+
fun set(profileId: UUID)
86+
87+
/**
88+
* Unset the current profile id in Glean.
89+
*/
90+
fun unset()
91+
}
92+
93+
/**
94+
* Represents the profile id used by Glean for usage reporting.
95+
*/
96+
class UsageProfileId : GleanProfileId {
97+
98+
/**
99+
* Glean doesn't have an API to remove a value,
100+
* so we have to use this canary value.
101+
* (would also allow us to notice if we ever accidentally sent data after we shouldn't).
102+
*/
103+
companion object {
104+
private const val CANARY_VALUE = "beefbeef-beef-beef-beef-beeefbeefbee"
105+
}
106+
107+
override fun generateAndSet(): UUID = Usage.profileId.generateAndSet()
108+
override fun set(profileId: UUID) {
109+
Usage.profileId.set(profileId)
110+
}
111+
112+
override fun unset() {
113+
Usage.profileId.set(UUID.fromString(CANARY_VALUE))
114+
}
115+
}
116+
117+
/**
118+
* An abstraction to represent the storage mechanism within the app for a Glean profile id.
119+
*/
120+
interface GleanProfileIdStore {
121+
/**
122+
* Property allowing access to the profile id which is stored.
123+
*/
124+
var profileId: String?
125+
126+
/**
127+
* Remove the stored profile id.
128+
*/
129+
fun clear()
130+
}
131+
132+
/**
133+
* The actual preference store used to store the Glean profile id.
134+
*/
135+
class GleanProfileIdPreferenceStore(context: Context) : GleanProfileIdStore {
136+
private val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
137+
private val preferenceKey = context.getPreferenceKey(R.string.pref_key_glean_usage_profile_id)
138+
139+
override var profileId: String?
140+
get() = defaultSharedPreferences.getString(
141+
preferenceKey,
142+
null,
143+
)
144+
set(value) {
145+
defaultSharedPreferences.edit()
146+
.putString(
147+
preferenceKey,
148+
value,
149+
).apply()
150+
}
151+
152+
override fun clear() {
153+
defaultSharedPreferences.edit()
154+
.remove(preferenceKey).apply()
155+
}
45156
}

mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/metrics/GleanUsageReportingMetricsServiceTest.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ import org.junit.Assert.assertNotNull
99
import org.junit.Assert.assertNull
1010
import org.junit.Assert.assertTrue
1111
import org.junit.Test
12+
import org.mozilla.fenix.components.metrics.fake.FakeGleanProfileId
13+
import org.mozilla.fenix.components.metrics.fake.FakeGleanProfileIdStore
1214
import org.mozilla.fenix.components.metrics.fake.FakeGleanUsageReporting
1315
import org.mozilla.fenix.components.metrics.fake.FakeLifecycleEventObserver
1416
import org.mozilla.fenix.components.metrics.fake.FakeLifecycleOwner
1517

16-
class GleanUsageReportingMetricsServiceTest {
18+
internal class GleanUsageReportingMetricsServiceTest {
1719

1820
private val fakeLifecycleOwner = FakeLifecycleOwner()
1921
private val fakeLifecycleEventObserver = FakeLifecycleEventObserver()
@@ -72,5 +74,7 @@ class GleanUsageReportingMetricsServiceTest {
7274
lifecycleOwner = fakeLifecycleOwner,
7375
gleanUsageReportingLifecycleObserver = fakeLifecycleEventObserver,
7476
gleanUsageReporting = fakeGleanUsageReporting,
77+
gleanProfileId = FakeGleanProfileId(),
78+
gleanProfileIdStore = FakeGleanProfileIdStore(),
7579
)
7680
}

0 commit comments

Comments
 (0)