For #8034: Create a post-visual completeness executor
Create an object that will execute its enqued tasks when Fenix is visually complete.fennec/beta
parent
af19913a16
commit
f9b716286a
@ -0,0 +1,14 @@
|
||||
/* 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.components
|
||||
|
||||
import org.mozilla.fenix.utils.StartupTaskManager
|
||||
|
||||
/**
|
||||
* Component group for all functionality related to performance.
|
||||
*/
|
||||
class PerformanceComponent {
|
||||
val visualCompletenessTaskManager by lazy { StartupTaskManager() }
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/* 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.utils
|
||||
|
||||
import org.mozilla.gecko.util.ThreadUtils
|
||||
import java.lang.IllegalStateException
|
||||
|
||||
typealias StartupTask = () -> Unit
|
||||
|
||||
/**
|
||||
* A queue of tasks that are performed at specific points during Fenix startup.
|
||||
*
|
||||
* This queue contains a list of startup tasks. Each task in the queue will be started once Fenix
|
||||
* is visually complete.
|
||||
*
|
||||
* This class is not thread safe and should only be called from the main thread.
|
||||
*/
|
||||
class StartupTaskManager {
|
||||
private var tasks = mutableListOf<StartupTask>()
|
||||
private var hasStarted = false
|
||||
private set
|
||||
|
||||
/**
|
||||
* Add a task to the queue.
|
||||
* Each task will execute on the main thread.
|
||||
*
|
||||
* @param task: The task to add to the queue.
|
||||
*/
|
||||
@Synchronized
|
||||
fun add(task: StartupTask) {
|
||||
ThreadUtils.assertOnUiThread()
|
||||
if (hasStarted) {
|
||||
throw IllegalStateException("New tasks should not be added because queue already " +
|
||||
"started, and these newly added tasks will not execute.")
|
||||
}
|
||||
|
||||
tasks.add(task)
|
||||
}
|
||||
|
||||
/**
|
||||
* Start all tasks in the queue. When all the tasks have been started,
|
||||
* clear the queue.
|
||||
*/
|
||||
fun start() {
|
||||
ThreadUtils.assertOnUiThread()
|
||||
hasStarted = true
|
||||
|
||||
tasks.forEach { it.invoke() }
|
||||
|
||||
// Anything captured by the lambda will remain captured if we hold on to these tasks,
|
||||
// which takes up more memory than we need to.
|
||||
tasks.clear()
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/* 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.session
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.os.Bundle
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.IntentReceiverActivity
|
||||
import org.mozilla.fenix.browser.BrowserPerformanceTestActivity
|
||||
import org.mozilla.fenix.settings.account.AuthIntentReceiverActivity
|
||||
import org.mozilla.fenix.utils.StartupTaskManager
|
||||
import org.mozilla.fenix.widget.VoiceSearchActivity
|
||||
|
||||
/**
|
||||
* These callbacks handle binding performance code to the activity lifecycle.
|
||||
*/
|
||||
@SuppressWarnings("EmptyFunctionBlock")
|
||||
class PerformanceActivityLifecycleCallbacks(
|
||||
private val visualCompletenessTaskManager: StartupTaskManager
|
||||
) : Application.ActivityLifecycleCallbacks {
|
||||
|
||||
override fun onActivityCreated(activity: Activity, bundle: Bundle?) {
|
||||
ifNecessaryPostVisualCompleteness(activity)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if it is a terminal activity, or false if it
|
||||
* an activity used in transition.
|
||||
*/
|
||||
private fun isTransientActivity(activity: Activity): Boolean {
|
||||
// These are the current list of non terminal activites.
|
||||
// They have been whitelisted in case new activities are added to the application
|
||||
// to ensure these new activities would not crash the application.
|
||||
return isTransientActivityInMigrationVariant(activity) ||
|
||||
(activity is IntentReceiverActivity) ||
|
||||
(activity is VoiceSearchActivity) ||
|
||||
(activity is AuthIntentReceiverActivity) ||
|
||||
(activity is BrowserPerformanceTestActivity)
|
||||
}
|
||||
|
||||
/**
|
||||
* This starts the StartupTaskManager, eitther delayed or right away, if the activity is a
|
||||
* terminal activity. If not, do nothing.
|
||||
*/
|
||||
private fun ifNecessaryPostVisualCompleteness(activity: Activity) {
|
||||
fun shouldStartVisualCompletenessQueueImmediately(): Boolean {
|
||||
return !isTransientActivity(activity)
|
||||
}
|
||||
|
||||
if (activity is HomeActivity) {
|
||||
// We should delay the visualCompletenessTaskManager when reaching the HomeActivity
|
||||
// to ensure all tasks are delayed until after visual completeness
|
||||
activity.postVisualCompletenessQueue(visualCompletenessTaskManager)
|
||||
} else if (shouldStartVisualCompletenessQueueImmediately()) {
|
||||
// If we do not go through the home activity, we have to start the tasks
|
||||
// immediately to avoid spending time implementing it.
|
||||
visualCompletenessTaskManager.start()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityStarted(activity: Activity?) {}
|
||||
override fun onActivityStopped(activity: Activity?) {}
|
||||
override fun onActivityResumed(activity: Activity?) {}
|
||||
override fun onActivityPaused(activity: Activity?) {}
|
||||
override fun onActivitySaveInstanceState(activity: Activity?, bundle: Bundle?) {}
|
||||
override fun onActivityDestroyed(activity: Activity?) {}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* The source files are different from migration and non migration variants.
|
||||
* We use this property to extend the [isTransientActivity] implementation for the
|
||||
* migration variants.
|
||||
*/
|
||||
var isTransientActivityInMigrationVariant: (Activity) -> Boolean = { false }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue