diff --git a/app/metrics.yaml b/app/metrics.yaml index a60f8e4f1..c47fddb55 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -1207,8 +1207,8 @@ metrics: start_reason_activity_error: type: boolean description: | - The `AppStartReasonProvider.ActivityLifecycleCallbacks.onCreate` was - unexpectedly called twice. We can use this metric to validate our + The `AppStartReasonProvider.ActivityLifecycleCallbacks.onActivityCreated` + was unexpectedly called twice. We can use this metric to validate our assumptions about how these APIs are called. This probe can be removed once we validate these assumptions. bugs: @@ -1221,6 +1221,23 @@ metrics: - perf-android-fe@mozilla.com - mcomella@mozilla.com expires: "2021-08-11" + activity_state_provider_error: + type: boolean + description: | + The `StartupActivityStateProvider...onActivityStarted` was unexpectedly + called twice. We can use this metric to validate our assumptions about + how these APIs are called. This probe can be removed once we validate + these assumptions. + bugs: + - https://github.com/mozilla-mobile/fenix/issues/18426 + data_reviews: + - TODO + data_sensitivity: + - technical + notification_emails: + - perf-android-fe@mozilla.com + - mcomella@mozilla.com + expires: "2021-08-11" preferences: show_search_suggestions: diff --git a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt index 568d8a3ca..22657333f 100644 --- a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt +++ b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt @@ -51,7 +51,6 @@ import org.mozilla.fenix.components.metrics.MetricServiceType import org.mozilla.fenix.components.metrics.SecurePrefsTelemetry import org.mozilla.fenix.ext.measureNoInline import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.perf.AppStartReasonProvider import org.mozilla.fenix.perf.ProfilerMarkerFactProcessor import org.mozilla.fenix.perf.StartupTimeline import org.mozilla.fenix.perf.StorageStatsMetrics @@ -192,6 +191,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider { // } components.appStartReasonProvider.registerInAppOnCreate(this) + components.startupActivityStateProvider.registerInAppOnCreate(this) initVisualCompletenessQueueAndQueueTasks() components.appStartupTelemetry.onFenixApplicationOnCreate() diff --git a/app/src/main/java/org/mozilla/fenix/components/Components.kt b/app/src/main/java/org/mozilla/fenix/components/Components.kt index b63095a0b..9990d32fb 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Components.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Components.kt @@ -29,6 +29,7 @@ import org.mozilla.fenix.components.metrics.AppStartupTelemetry import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.perf.AppStartReasonProvider +import org.mozilla.fenix.perf.StartupActivityStateProvider import org.mozilla.fenix.perf.lazyMonitored import org.mozilla.fenix.utils.ClipboardHandler import org.mozilla.fenix.utils.Mockable @@ -173,4 +174,5 @@ class Components(private val context: Context) { } val appStartReasonProvider by lazyMonitored { AppStartReasonProvider() } + val startupActivityStateProvider by lazyMonitored { StartupActivityStateProvider() } } diff --git a/app/src/main/java/org/mozilla/fenix/perf/StartupActivityStateProvider.kt b/app/src/main/java/org/mozilla/fenix/perf/StartupActivityStateProvider.kt new file mode 100644 index 000000000..693281902 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/perf/StartupActivityStateProvider.kt @@ -0,0 +1,77 @@ +/* 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.perf + +import android.app.Activity +import android.app.Application +import mozilla.components.support.base.log.logger.Logger +import org.mozilla.fenix.GleanMetrics.Metrics +import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.android.DefaultActivityLifecycleCallbacks + +private val logger = Logger("StartupActivityState") + +/** + * Provides meta information about the Activities that occur during the initial parts of start up + * and their state. + * + * [registerInAppOnCreate] must be called for this class to work correctly. + */ +class StartupActivityStateProvider { + + enum class FirstForegroundActivity { + TO_BE_DETERMINED, + HOME_ACTIVITY, + UNKNOWN + } + + enum class FirstForegroundActivityState { + BEFORE_FOREGROUND, + CURRENTLY_FOREGROUNDED, + AFTER_FOREGROUND, + } + + /** The first [Activity] that has been foreground in this process lifetime. */ + var firstForegroundActivityOfProcess = FirstForegroundActivity.TO_BE_DETERMINED + private set + + /** The current foreground state of the [firstForegroundActivityOfProcess]. */ + var firstForegroundActivityState = FirstForegroundActivityState.BEFORE_FOREGROUND + private set + + /** + * Registers the handlers needed by this class: this is expected to be called from + * [Application.onCreate]. + */ + fun registerInAppOnCreate(application: Application) { + application.registerActivityLifecycleCallbacks(StateActivityLifecycleCallbacks()) + } + + private inner class StateActivityLifecycleCallbacks : DefaultActivityLifecycleCallbacks { + override fun onActivityStarted(activity: Activity) { + if (firstForegroundActivityOfProcess != FirstForegroundActivity.TO_BE_DETERMINED) { + // This should never happen because we remove the listener in onStop and old activities + // should be stopped before new ones are started but the call order may change slightly + // between devices. + Metrics.activityStateProviderError.set(true) + logger.error("StartupActivityStateProvider...onActivityStarted unexpectedly called twice.") + return + } + + firstForegroundActivityOfProcess = when (activity) { + is HomeActivity -> FirstForegroundActivity.HOME_ACTIVITY + else -> FirstForegroundActivity.UNKNOWN + } + + firstForegroundActivityState = FirstForegroundActivityState.CURRENTLY_FOREGROUNDED + } + + override fun onActivityStopped(activity: Activity) { + firstForegroundActivityState = FirstForegroundActivityState.AFTER_FOREGROUND + + activity.application.unregisterActivityLifecycleCallbacks(this) // no more state updates needed. + } + } +} diff --git a/docs/metrics.md b/docs/metrics.md index 2c88c57ea..d78df39fe 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -312,6 +312,7 @@ In addition to those built-in metrics, the following metrics are added to the pi | engine_tab.kills |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |How often was the content process of a foreground (selected) or background tab killed. |[mozilla-mobile/fenix#17864](https://github.com/mozilla-mobile/fenix/pull/17864)||2021-12-31 |1 | | events.normal_and_private_uri_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter of URIs visited by the user in the current session, including page reloads. This includes private browsing. This does not include background page requests and URIs from embedded pages but may be incremented without user interaction by website scripts that programmatically redirect to a new location. |[mozilla-mobile/fenix#17935](https://github.com/mozilla-mobile/fenix/pull/17935)||2022-08-01 |2 | | events.total_uri_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter of URIs visited by the user in the current session, including page reloads. This does not include background page requests and URIs from embedded pages or private browsing but may be incremented without user interaction by website scripts that programmatically redirect to a new location. |[mozilla-mobile/fenix#1785](https://github.com/mozilla-mobile/fenix/pull/1785), [mozilla-mobile/fenix#8314](https://github.com/mozilla-mobile/fenix/pull/8314), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 | +| metrics.activity_state_provider_error |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |The `StartupActivityStateProvider...onActivityStarted` was unexpectedly called twice. We can use this metric to validate our assumptions about how these APIs are called. This probe can be removed once we validate these assumptions. |[Review 1](TODO)||2021-08-11 |1 | | metrics.adjust_ad_group |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string containing the Adjust ad group ID from which the user installed Fenix. This will not send on the first session the user runs. If the install is organic, this will be empty. |[mozilla-mobile/fenix#9253](https://github.com/mozilla-mobile/fenix/pull/9253), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 | | metrics.adjust_campaign |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string containing the Adjust campaign ID from which the user installed Fenix. This will not send on the first session the user runs. If the install is organic, this will be empty. |[mozilla-mobile/fenix#5579](https://github.com/mozilla-mobile/fenix/pull/5579), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |1 | | metrics.adjust_creative |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string containing the Adjust creative ID from which the user installed Fenix. This will not send on the first session the user runs. If the install is organic, this will be empty. |[mozilla-mobile/fenix#9253](https://github.com/mozilla-mobile/fenix/pull/9253), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 | @@ -331,7 +332,7 @@ In addition to those built-in metrics, the following metrics are added to the pi | metrics.recently_used_pwa_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter that indicates how many PWAs a user has recently used. Threshold for "recency" set in HomeActivity#PWA_RECENTLY_USED_THRESHOLD. Currently we are not told by the OS when a PWA is removed by the user, so we use the "recently used" heuristic to judge how many PWAs are still active, as a proxy for "installed". This value will only be set if the user has at least *one* recently used PWA. If they have 0, this metric will not be sent, resulting in a null value during analysis on the server-side. To disambiguate between a failed `recently_used_pwa_count` metric and 0 recent PWAs, please see `has_recent_pwas`. |[mozilla-mobile/fenix#11982](https://github.com/mozilla-mobile/fenix/pull/11982#pullrequestreview-437963817), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 | | metrics.search_count |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |The labels for this counter are `.`. If the search engine is bundled with Fenix `search-engine-name` will be the name of the search engine. If it's a custom search engine (defined: https://github.com/mozilla-mobile/fenix/issues/1607) the value will be `custom`. `source` will be: `action`, `suggestion`, `widget`, `shortcut`, `topsite` (depending on the source from which the search started). Also added the `other` option for the source but it should never enter on this case. |[mozilla-mobile/fenix#1677](https://github.com/mozilla-mobile/fenix/pull/1677), [mozilla-mobile/fenix#5216](https://github.com/mozilla-mobile/fenix/pull/5216), [mozilla-mobile/fenix#7310](https://github.com/mozilla-mobile/fenix/pull/7310), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |1, 2 | | metrics.search_widget_installed |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the search widget is installed |[mozilla-mobile/fenix#10958](https://github.com/mozilla-mobile/fenix/pull/10958), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 | -| metrics.start_reason_activity_error |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |The `AppStartReasonProvider.ActivityLifecycleCallbacks.onCreate` was unexpectedly called twice. We can use this metric to validate our assumptions about how these APIs are called. This probe can be removed once we validate these assumptions. |[Review 1](TODO)||2021-08-11 |1 | +| metrics.start_reason_activity_error |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |The `AppStartReasonProvider.ActivityLifecycleCallbacks.onActivityCreated` was unexpectedly called twice. We can use this metric to validate our assumptions about how these APIs are called. This probe can be removed once we validate these assumptions. |[Review 1](TODO)||2021-08-11 |1 | | metrics.start_reason_process_error |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |The `AppStartReasonProvider.ProcessLifecycleObserver.onCreate` was unexpectedly called twice. We can use this metric to validate our assumptions about how these APIs are called. This probe can be removed once we validate these assumptions. |[Review 1](TODO)||2021-08-11 |1 | | metrics.tab_view_setting |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string that indicates the setting for tab view: GRID, LIST |[mozilla-mobile/fenix#15811](https://github.com/mozilla-mobile/fenix/pull/15811#issuecomment-706402952)||2021-08-01 |2 | | metrics.tabs_open_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter that indicates how many NORMAL tabs a user has open. This value will only be set if the user has at least *one* open tab. If they have 0, this ping will not get sent, resulting in a null value. To disambiguate between a failed `tabs_open_count` ping and 0 open tabs, please see `has_open_tabs`. |[mozilla-mobile/fenix#12024](https://github.com/mozilla-mobile/fenix/pull/12024), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |