/* 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.view.View import androidx.core.view.doOnPreDraw import mozilla.components.support.ktx.android.view.reportFullyDrawnSafe import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.home.sessioncontrol.viewholders.topsites.TopSiteItemViewHolder import org.mozilla.fenix.perf.StartupTimelineStateMachine.StartupDestination.APP_LINK import org.mozilla.fenix.perf.StartupTimelineStateMachine.StartupDestination.HOMESCREEN import org.mozilla.fenix.perf.StartupTimelineStateMachine.StartupState /** * Instruments the Android framework method [Activity.reportFullyDrawn], which prints time to visual * completeness to logcat. * * At the time of writing (2020-02-26), this functionality is tightly coupled to FNPRMS, our internal * startup measurement system. However, these values may also appear in the Google Play Vitals * dashboards. */ class StartupReportFullyDrawn { // Ideally we'd incorporate this state into the StartupState but we're short on implementation time. private var isInstrumented = false /** * Instruments "visually complete" cold startup time for app link for use with FNPRMS. */ fun onActivityCreateEndHome(state: StartupState, activity: HomeActivity) { if (!isInstrumented && state is StartupState.Cold && state.destination == APP_LINK) { // Instrumenting the first frame drawn should be good enough for app link for now. isInstrumented = true attachReportFullyDrawn(activity, activity.findViewById(R.id.rootContainer)) } } /** * Instruments "visually complete" cold startup time to homescreen for use with FNPRMS. * * For FNPRMS, we define "visually complete" to be when top sites is loaded with placeholders; * the animation to display top sites will occur after this point, as will the asynchronous * loading of the actual top sites icons. Our focus for visually complete is usability. * There are no tabs available in our FNPRMS tests so they are ignored for this instrumentation. */ fun onTopSitesItemBound(state: StartupState, holder: TopSiteItemViewHolder) { if (!isInstrumented && state is StartupState.Cold && state.destination == HOMESCREEN) { isInstrumented = true // Ideally we wouldn't cast to HomeActivity but we want to save implementation time. val view = holder.itemView attachReportFullyDrawn(view.context as HomeActivity, view) } } private fun attachReportFullyDrawn(activity: Activity, view: View) { // For greater accuracy, we could add an onDrawListener instead of a preDrawListener but: // - single use onDrawListeners are not built-in and it's non-trivial to write one // - the difference in timing is minimal (< 7ms on Pixel 2) // - if we compare against another app using a preDrawListener, as we are with Fennec, it // should be comparable view.doOnPreDraw { activity.reportFullyDrawnSafe(Performance.logger) } } }