Skip to content

Commit

Permalink
For mozilla-mobile#18836: add isHotStartForStartedActivity and tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
mcomella committed Apr 14, 2021
1 parent b92dfbe commit f39b2a9
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
31 changes: 31 additions & 0 deletions app/src/main/java/org/mozilla/fenix/perf/StartupStateProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,35 @@ class StartupStateProvider(
)
return isLastActivityCreatedStillStarted
}

/**
* Returns true if the current startup state is HOT and the currently started activity is the
* first started activity for this start up (i.e. we can use it for performance measurements).
*
* This method must be called after the foreground activity is STARTED.
*/
fun isHotStartForStartedActivity(activityClass: Class<out Activity>): Boolean {
// A hot start means:
// - the app was backgrounded and has since been started
// - the first started activity since the app was started is still active.
// - that activity was not created before being started
//
// For the activity log, we expect:
// [... App-STOPPED, ... Activity-STARTED, App-STARTED]
// where:
// - App-STOPPED is the last STOPPED seen
// - App-CREATED is NOT called for this activity
// - we're assuming App-STARTED will only be last if one activity is started (as observed)
if (!startupLog.log.contains(LogEntry.AppStopped)) {
return false // if the app hasn't been stopped, it's not a hot start.
}
val afterLastStopped = startupLog.log.takeLastWhile { it != LogEntry.AppStopped }

val isLastActivityStartedStillStarted = afterLastStopped.takeLast(2) == listOf(
LogEntry.ActivityStarted(activityClass),
LogEntry.AppStarted
)
return !afterLastStopped.contains(LogEntry.ActivityCreated(activityClass)) &&
isLastActivityStartedStillStarted
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,27 @@ class StartupStateProviderTest {
}
}

@Test
fun `GIVEN the app started for an activity WHEN is cold start THEN hot start is false`() {
forEachColdStartEntries { index ->
assertFalse("$index", provider.isHotStartForStartedActivity(homeActivityClass))
}
}

@Test
fun `GIVEN the app started for an activity WHEN is warm start THEN hot start is false`() {
forEachWarmStartEntries { index ->
assertFalse("$index", provider.isHotStartForStartedActivity(homeActivityClass))
}
}

@Test
fun `GIVEN the app started for an activity WHEN is hot start THEN hot start is true` () {
forEachHotStartEntries { index ->
assertTrue("$index", provider.isHotStartForStartedActivity(homeActivityClass))
}
}

@Test
fun `GIVEN the app started for an activity WHEN we launched HA through a drawing IntentRA THEN start up is not cold`() {
// These entries mimic observed behavior for local code changes.
Expand Down Expand Up @@ -111,6 +132,21 @@ class StartupStateProviderTest {
assertFalse(provider.isWarmStartForStartedActivity(homeActivityClass))
}

@Test
fun `GIVEN the app started for an activity WHEN we launched HA through a drawing IntentRA THEN start up is not hot`() {
// These entries mimic observed behavior for local code changes.
logEntries.addAll(listOf(
LogEntry.AppStopped,
LogEntry.ActivityStopped(homeActivityClass),
LogEntry.ActivityCreated(irActivityClass),
LogEntry.ActivityStarted(irActivityClass),
LogEntry.AppStarted,
LogEntry.ActivityStarted(homeActivityClass),
LogEntry.ActivityStopped(irActivityClass)
))
assertFalse(provider.isHotStartForStartedActivity(homeActivityClass))
}

@Test
fun `GIVEN the app started for an activity WHEN two HomeActivities are created THEN start up is not cold`() {
// We're making an assumption about how this would work based on previous observed patterns.
Expand Down Expand Up @@ -181,6 +217,26 @@ class StartupStateProviderTest {
assertFalse(provider.isWarmStartForStartedActivity(homeActivityClass))
}

@Test
fun `GIVEN the app has not been stopped WHEN an activity has not been created THEN it's not a hot start`() {
assertFalse(provider.isHotStartForStartedActivity(homeActivityClass))
}

@Test
fun `GIVEN the app has been stopped WHEN an activity has not been created THEN it's not a hot start`() {
logEntries.add(LogEntry.AppStopped)
assertFalse(provider.isHotStartForStartedActivity(homeActivityClass))
}

@Test
fun `GIVEN the app has been stopped WHEN an activity has not been started THEN it's not a hot start`() {
logEntries.addAll(listOf(
LogEntry.AppStopped,
LogEntry.ActivityCreated(homeActivityClass)
))
assertFalse(provider.isHotStartForStartedActivity(homeActivityClass))
}

private fun forEachColdStartEntries(block: (index: Int) -> Unit) {
// These entries mimic observed behavior.
//
Expand Down

0 comments on commit f39b2a9

Please sign in to comment.