Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #4466: CPU Usage performance metrics logging #4623

Merged
merged 74 commits into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
c6536fc
initial draft implementation
Sarthak2601 Sep 26, 2022
34ca356
nits
Sarthak2601 Sep 26, 2022
0a41f9f
nits
Sarthak2601 Sep 26, 2022
8d58d4a
new approach for bg and fg periodic cpu logging
Sarthak2601 Oct 7, 2022
b013988
nits
Sarthak2601 Oct 7, 2022
2e2210d
num of cores fix for all versions
Sarthak2601 Oct 7, 2022
9e433bf
nits
Sarthak2601 Oct 7, 2022
ce97bdb
nits
Sarthak2601 Oct 10, 2022
031c413
nit
Sarthak2601 Oct 10, 2022
b7bed33
updates
Sarthak2601 Oct 11, 2022
2186f27
simplification of app state calculation
Sarthak2601 Oct 11, 2022
a4d3f69
updates
Sarthak2601 Oct 12, 2022
2d5ca36
nits
Sarthak2601 Oct 12, 2022
bc92b91
nit
Sarthak2601 Oct 12, 2022
20d0198
waking effect update
Sarthak2601 Oct 12, 2022
e563fe6
nits
Sarthak2601 Oct 12, 2022
ebe71f8
cpu logging actor update
Sarthak2601 Oct 13, 2022
f9dc705
nits
Sarthak2601 Oct 13, 2022
6f8fbe8
structuring and comments for snapshotter
Sarthak2601 Oct 14, 2022
9316738
nits
Sarthak2601 Oct 14, 2022
0fc1cf9
nits
Sarthak2601 Oct 14, 2022
a3e0335
Merge branch 'develop' into performance-metrics-cpu-usage
Sarthak2601 Oct 14, 2022
b4c2623
test fixes
Sarthak2601 Oct 14, 2022
5a5d13b
nits
Sarthak2601 Oct 14, 2022
5c62c4f
removal of ActivityLifecycleObserver
Sarthak2601 Oct 14, 2022
a5bb02a
code restructure and assessorImpl tests
Sarthak2601 Oct 15, 2022
5c3f369
snapshotter tests
Sarthak2601 Oct 16, 2022
bf23e95
nits
Sarthak2601 Oct 16, 2022
494b2c2
test file fixes - gradle
Sarthak2601 Oct 17, 2022
cc99a78
nits
Sarthak2601 Oct 17, 2022
f8be80a
bazel build fix
Sarthak2601 Oct 17, 2022
d9061a0
bazel build fix
Sarthak2601 Oct 17, 2022
086685b
test fixes
Sarthak2601 Oct 17, 2022
4a7dd89
(nit + static checks) fixes
Sarthak2601 Oct 17, 2022
32a9e78
module test
Sarthak2601 Oct 18, 2022
fc99950
nits
Sarthak2601 Oct 18, 2022
804be5d
nits
Sarthak2601 Oct 18, 2022
ac7925f
nits
Sarthak2601 Oct 18, 2022
335fc1e
test fix
Sarthak2601 Oct 18, 2022
da0bab5
review changes (nits, snapshotter tests, etc)
Sarthak2601 Oct 19, 2022
a17c7a4
nits
Sarthak2601 Oct 19, 2022
d93d668
assessor tests
Sarthak2601 Oct 19, 2022
4982e6a
Merge branch 'develop' into performance-metrics-cpu-usage
Sarthak2601 Oct 19, 2022
c023b5c
observer test fix
Sarthak2601 Oct 20, 2022
3584c61
bazel build fix
Sarthak2601 Oct 20, 2022
5fb2a3d
nit fix
Sarthak2601 Oct 20, 2022
950b871
bazel fixes
Sarthak2601 Oct 20, 2022
6e442e4
nits
Sarthak2601 Oct 20, 2022
bb1c1cf
updates post review
Sarthak2601 Oct 20, 2022
b5e420d
bazel build fix
Sarthak2601 Oct 20, 2022
96d1756
nits
Sarthak2601 Oct 20, 2022
d5e8d7e
parameterized tests
Sarthak2601 Oct 20, 2022
78e83dd
domain test fixes
Sarthak2601 Oct 20, 2022
4e5c3b3
nits
Sarthak2601 Oct 20, 2022
4187e50
bazel fix
Sarthak2601 Oct 21, 2022
f746a54
review updates
Sarthak2601 Oct 22, 2022
286e7e8
nits
Sarthak2601 Oct 22, 2022
d485b31
bazel fix
Sarthak2601 Oct 22, 2022
e97df2c
additional metrics logging
Sarthak2601 Oct 22, 2022
0a63011
review updates
Sarthak2601 Oct 23, 2022
6d837a1
base iconification change
Sarthak2601 Oct 23, 2022
8f8af9e
additional metric logging
Sarthak2601 Oct 24, 2022
73f73a8
private fun
Sarthak2601 Oct 24, 2022
2634150
additional tests
Sarthak2601 Oct 25, 2022
b8cfb3a
cpu snapshotter tests
Sarthak2601 Oct 28, 2022
652bf0e
snapshotter initialization modifications
Sarthak2601 Oct 29, 2022
f423345
Merge branch 'develop' into performance-metrics-cpu-usage
Sarthak2601 Oct 29, 2022
5f3ed8f
nits
Sarthak2601 Oct 29, 2022
2b68574
test fixes.
Sarthak2601 Oct 29, 2022
62e5edf
updates
Sarthak2601 Oct 31, 2022
0f866c4
Merge branch 'develop' into performance-metrics-cpu-usage
Sarthak2601 Oct 31, 2022
7f57752
test fix
Sarthak2601 Nov 1, 2022
2c1177a
Merge branch 'develop' into performance-metrics-cpu-usage
Sarthak2601 Nov 1, 2022
326ecd8
nit
Sarthak2601 Nov 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,11 @@ annotation class ForegroundCpuLoggingTimePeriodMillis
*/
@Qualifier
annotation class BackgroundCpuLoggingTimePeriodMillis

/**
* Corresponds to an injectable application-level [Long] that corresponds to the number of
* milliseconds after which the initial iconification is set to background if it is uninitialized
* until that point.
*/
@Qualifier
annotation class InitialIconificationCutOffTimePeriodMillis
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ import kotlinx.coroutines.channels.actor
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.oppia.android.app.model.ScreenName
import org.oppia.android.app.model.ScreenName.BACKGROUND_SCREEN
import org.oppia.android.app.model.ScreenName.FOREGROUND_SCREEN
import org.oppia.android.app.model.ScreenName.SCREEN_NAME_UNSPECIFIED
import org.oppia.android.util.logging.ConsoleLogger
import org.oppia.android.util.logging.ExceptionLogger
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsAssessor
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsAssessor.AppIconification
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsAssessor.AppIconification.APP_IN_BACKGROUND
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsAssessor.AppIconification.APP_IN_FOREGROUND
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsAssessor.AppIconification.UNINITIALIZED
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsAssessor.CpuSnapshot

/**
Expand All @@ -24,12 +30,13 @@ class CpuPerformanceSnapshotter(
private val initialIconification: AppIconification,
private val consoleLogger: ConsoleLogger,
private val exceptionLogger: ExceptionLogger,
private val performanceMetricsAssessor: PerformanceMetricsAssessor,
private val foregroundCpuLoggingTimePeriodMillis: Long,
private val backgroundCpuLoggingTimePeriodMillis: Long,
private val performanceMetricsAssessor: PerformanceMetricsAssessor
private val initialIconificationCutOffTimePeriodMillis: Long
) {

private val commandQueue by lazy { createCommandQueueActor() }
private val commandQueue = createCommandQueueActor()
BenHenning marked this conversation as resolved.
Show resolved Hide resolved

/** Updates the current [AppIconification] in accordance with the app's state changes. */
fun updateAppIconification(newIconification: AppIconification) {
Expand All @@ -38,23 +45,24 @@ class CpuPerformanceSnapshotter(

private fun createCommandQueueActor(): SendChannel<CommandMessage> {
var currentIconification = initialIconification
var previousSnapshot =
performanceMetricsAssessor.computeCpuSnapshotAtCurrentTime()
var previousSnapshot = performanceMetricsAssessor.computeCpuSnapshotAtCurrentTime()
var switchIconificationCount = 0
val coroutineScope = CoroutineScope(backgroundCoroutineDispatcher)
return coroutineScope.actor<CommandMessage>(capacity = Channel.UNLIMITED) {
for (message in channel) {
when (message) {
is CommandMessage.SwitchIconification -> {
++switchIconificationCount
// Since there's a switch in the current iconification of the app, we'd cut short the
// existing delay and log the current CPU usage relative to the previously logged one
// without this explicit log command.
performanceMetricsAssessor.getRelativeCpuUsage(
previousSnapshot,
performanceMetricsAssessor.computeCpuSnapshotAtCurrentTime()
)?.let { relativeCpuUsage ->
sendLogSnapshotDiffCommand(relativeCpuUsage, currentIconification)
if (currentIconification != UNINITIALIZED) {
// Since there's a switch in the current iconification of the app, we'd cut short the
// existing delay and log the current CPU usage relative to the previously logged one
// without this explicit log command.
performanceMetricsAssessor.getRelativeCpuUsage(
previousSnapshot,
performanceMetricsAssessor.computeCpuSnapshotAtCurrentTime()
)?.let { relativeCpuUsage ->
sendLogSnapshotDiffCommand(relativeCpuUsage, currentIconification)
}
}
currentIconification = message.newIconification
previousSnapshot = performanceMetricsAssessor.computeCpuSnapshotAtCurrentTime()
Expand Down Expand Up @@ -88,7 +96,10 @@ class CpuPerformanceSnapshotter(
}
}.also {
CoroutineScope(backgroundCoroutineDispatcher).launch {
sendTakeSnapshotCommand(switchIconificationCount)
BenHenning marked this conversation as resolved.
Show resolved Hide resolved
delay(initialIconificationCutOffTimePeriodMillis)
if (currentIconification == UNINITIALIZED) {
sendSwitchIconificationCommand(APP_IN_BACKGROUND)
}
}
}
}
Expand All @@ -110,9 +121,7 @@ class CpuPerformanceSnapshotter(
private suspend fun sendScheduleTakeSnapshotCommand(
currentIconification: AppIconification,
switchId: Int
) {
commandQueue.send(CommandMessage.ScheduleTakeSnapshot(currentIconification, switchId))
}
) { commandQueue.send(CommandMessage.ScheduleTakeSnapshot(currentIconification, switchId)) }

private suspend fun sendTakeSnapshotCommand(switchId: Int) {
commandQueue.send(CommandMessage.TakeSnapshot(switchId))
Expand Down Expand Up @@ -188,13 +197,15 @@ class CpuPerformanceSnapshotter(

/** Returns an appropriate [ScreenName] on the basis of [AppIconification]. */
private fun AppIconification.toScreenName(): ScreenName = when (this) {
AppIconification.APP_IN_BACKGROUND -> ScreenName.BACKGROUND_SCREEN
AppIconification.APP_IN_FOREGROUND -> ScreenName.FOREGROUND_SCREEN
APP_IN_BACKGROUND -> BACKGROUND_SCREEN
APP_IN_FOREGROUND -> FOREGROUND_SCREEN
UNINITIALIZED -> SCREEN_NAME_UNSPECIFIED
}

/** Returns an appropriate delay time period in millis on the basis of [AppIconification]. */
private fun AppIconification.getDelay(): Long = when (this) {
AppIconification.APP_IN_BACKGROUND -> backgroundCpuLoggingTimePeriodMillis
AppIconification.APP_IN_FOREGROUND -> foregroundCpuLoggingTimePeriodMillis
APP_IN_BACKGROUND -> backgroundCpuLoggingTimePeriodMillis
APP_IN_FOREGROUND -> foregroundCpuLoggingTimePeriodMillis
UNINITIALIZED -> initialIconificationCutOffTimePeriodMillis
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,21 @@ class CpuPerformanceSnapshotterModule {
performanceMetricsLogger: PerformanceMetricsLogger,
consoleLogger: ConsoleLogger,
exceptionLogger: ExceptionLogger,
performanceMetricsAssessor: PerformanceMetricsAssessor,
@BackgroundDispatcher backgroundCoroutineDispatcher: CoroutineDispatcher,
@ForegroundCpuLoggingTimePeriodMillis foregroundCpuLoggingTimePeriodMillis: Long,
@BackgroundCpuLoggingTimePeriodMillis backgroundCpuLoggingTimePeriodMillis: Long,
@BackgroundDispatcher backgroundCoroutineDispatcher: CoroutineDispatcher,
performanceMetricsAssessor: PerformanceMetricsAssessor
@InitialIconificationCutOffTimePeriodMillis initialIconificationCutOffTimePeriodMillis: Long
): CpuPerformanceSnapshotter = CpuPerformanceSnapshotter(
backgroundCoroutineDispatcher,
performanceMetricsLogger,
PerformanceMetricsAssessor.AppIconification.APP_IN_BACKGROUND,
PerformanceMetricsAssessor.AppIconification.UNINITIALIZED,
BenHenning marked this conversation as resolved.
Show resolved Hide resolved
consoleLogger,
exceptionLogger,
performanceMetricsAssessor,
foregroundCpuLoggingTimePeriodMillis,
backgroundCpuLoggingTimePeriodMillis,
performanceMetricsAssessor
initialIconificationCutOffTimePeriodMillis
)

@Provides
Expand All @@ -42,4 +44,8 @@ class CpuPerformanceSnapshotterModule {
@Provides
@BackgroundCpuLoggingTimePeriodMillis
fun provideBackgroundCpuLoggingTimePeriodMillis(): Long = TimeUnit.MINUTES.toMillis(60)

@Provides
@InitialIconificationCutOffTimePeriodMillis
fun provideInitialIconificationCutOffTimePeriodMillis(): Long = TimeUnit.SECONDS.toMillis(60)
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsAsses
import org.oppia.android.util.networking.NetworkConnectionUtilDebugModule
import org.robolectric.annotation.Config
import org.robolectric.annotation.LooperMode
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton

Expand Down Expand Up @@ -68,6 +69,9 @@ class CpuPerformanceSnapshotterTest {
@field:[JvmField Inject BackgroundCpuLoggingTimePeriodMillis]
var backgroundCpuLoggingTimePeriodMillis: Long = Long.MIN_VALUE

@field:[JvmField Inject InitialIconificationCutOffTimePeriodMillis]
var initialIconificationCutOffTimePeriodMillis: Long = Long.MIN_VALUE

@Before
fun setUp() {
TestPlatformParameterModule.forceEnablePerformanceMetricsCollection(true)
Expand Down Expand Up @@ -109,19 +113,21 @@ class CpuPerformanceSnapshotterTest {
cpuPerformanceSnapshotter.updateAppIconification(APP_IN_BACKGROUND)
testCoroutineDispatchers.runCurrent()
testCoroutineDispatchers.advanceTimeBy(backgroundCpuLoggingTimePeriodMillis)
cpuPerformanceSnapshotter.updateAppIconification(APP_IN_FOREGROUND)
testCoroutineDispatchers.runCurrent()

val count = fakePerformanceMetricsEventLogger.getPerformanceMetricsEventListCount()
val latestEvents =
fakePerformanceMetricsEventLogger.getMostRecentPerformanceMetricsEvents(count)
// Event that got logged after time advancement.
// Event that got logged on third update call.
val latestEvent = latestEvents[count - 1]
// Event that got logged on second iconification update.
// Event that got logged after time advancement.
val secondLatestEvent = latestEvents[count - 2]
// Event that got logged on first iconification update.
// Event that got logged on second update call.
val thirdLatestEvent = latestEvents[count - 3]

assertThat(latestEvent.currentScreen).isEqualTo(ScreenName.BACKGROUND_SCREEN)
assertThat(secondLatestEvent.currentScreen).isEqualTo(ScreenName.FOREGROUND_SCREEN)
assertThat(secondLatestEvent.currentScreen).isEqualTo(ScreenName.BACKGROUND_SCREEN)
assertThat(thirdLatestEvent.currentScreen).isEqualTo(ScreenName.FOREGROUND_SCREEN)
}

Expand All @@ -130,6 +136,7 @@ class CpuPerformanceSnapshotterTest {
fakePerformanceMetricAssessor.setRelativeCpuUsage(TEST_CPU_USAGE_ONE)
cpuPerformanceSnapshotter.updateAppIconification(APP_IN_FOREGROUND)
testCoroutineDispatchers.runCurrent()
testCoroutineDispatchers.advanceTimeBy(foregroundCpuLoggingTimePeriodMillis)
BenHenning marked this conversation as resolved.
Show resolved Hide resolved
val firstEvent = fakePerformanceMetricsEventLogger.getMostRecentPerformanceMetricsEvent()

fakePerformanceMetricAssessor.setRelativeCpuUsage(TEST_CPU_USAGE_TWO)
Expand Down Expand Up @@ -163,6 +170,7 @@ class CpuPerformanceSnapshotterTest {
fakePerformanceMetricAssessor.setRelativeCpuUsage(TEST_CPU_USAGE_ONE)
cpuPerformanceSnapshotter.updateAppIconification(APP_IN_BACKGROUND)
testCoroutineDispatchers.runCurrent()
testCoroutineDispatchers.advanceTimeBy(backgroundCpuLoggingTimePeriodMillis)
val firstEvent = fakePerformanceMetricsEventLogger.getMostRecentPerformanceMetricsEvent()

fakePerformanceMetricAssessor.setRelativeCpuUsage(TEST_CPU_USAGE_TWO)
Expand Down Expand Up @@ -215,6 +223,7 @@ class CpuPerformanceSnapshotterTest {
fakePerformanceMetricAssessor.setRelativeCpuUsage(TEST_CPU_USAGE_ONE)
cpuPerformanceSnapshotter.updateAppIconification(APP_IN_FOREGROUND)
testCoroutineDispatchers.runCurrent()
testCoroutineDispatchers.advanceTimeBy(foregroundCpuLoggingTimePeriodMillis)

val latestEvent = fakePerformanceMetricsEventLogger.getMostRecentPerformanceMetricsEvent()

Expand All @@ -231,6 +240,127 @@ class CpuPerformanceSnapshotterTest {
assertThat(fakePerformanceMetricsEventLogger.noPerformanceMetricsEventsPresent()).isTrue()
}

@Test
fun testSnapshotter_onCreate_moveToForegroundBeforeCutOff_logsCpuUsageInForegroundAfterDelay() {
applicationLifecycleObserver.onCreate()
testCoroutineDispatchers.runCurrent()
// clearing up all app startup performance metrics: apk size and storage usage.
BenHenning marked this conversation as resolved.
Show resolved Hide resolved
fakePerformanceMetricsEventLogger.clearAllPerformanceMetricsEvents()
testCoroutineDispatchers.advanceTimeBy(1000)
applicationLifecycleObserver.onAppInForeground()
testCoroutineDispatchers.runCurrent()
testCoroutineDispatchers.advanceTimeBy(foregroundCpuLoggingTimePeriodMillis)

val count = fakePerformanceMetricsEventLogger.getPerformanceMetricsEventListCount()
val event = fakePerformanceMetricsEventLogger.getMostRecentPerformanceMetricsEvent()

assertThat(count).isEqualTo(1)
assertThat(event).isNotNull()
BenHenning marked this conversation as resolved.
Show resolved Hide resolved
assertThat(event.currentScreen).isEqualTo(ScreenName.FOREGROUND_SCREEN)
}

@Test
fun testSnapshotter_moveToFgBeforeCutOff_moveToBgBeforeDelayEnds_logsInFg_logsInBgAfterDelay() {
applicationLifecycleObserver.onCreate()
testCoroutineDispatchers.runCurrent()
// clearing up all app startup performance metrics: apk size and storage usage.
fakePerformanceMetricsEventLogger.clearAllPerformanceMetricsEvents()
testCoroutineDispatchers.advanceTimeBy(1000)
applicationLifecycleObserver.onAppInForeground()
testCoroutineDispatchers.runCurrent()
testCoroutineDispatchers.advanceTimeBy(TimeUnit.MINUTES.toMillis(2))
applicationLifecycleObserver.onAppInBackground()
testCoroutineDispatchers.runCurrent()
testCoroutineDispatchers.advanceTimeBy(backgroundCpuLoggingTimePeriodMillis)

val count = fakePerformanceMetricsEventLogger.getPerformanceMetricsEventListCount()
val events = fakePerformanceMetricsEventLogger.getMostRecentPerformanceMetricsEvents(count)

assertThat(count).isEqualTo(2)
assertThat(events[0].currentScreen).isEqualTo(ScreenName.FOREGROUND_SCREEN)
assertThat(events[1].currentScreen).isEqualTo(ScreenName.BACKGROUND_SCREEN)
}

@Test
fun testSnapshotter_moveToFgBeforeCutOff_moveToBgAfterFirstDelay_logsCpuWithCorrectIcon() {
applicationLifecycleObserver.onCreate()
testCoroutineDispatchers.runCurrent()
// clearing up all app startup performance metrics: apk size and storage usage.
fakePerformanceMetricsEventLogger.clearAllPerformanceMetricsEvents()
testCoroutineDispatchers.advanceTimeBy(1000)
applicationLifecycleObserver.onAppInForeground()
testCoroutineDispatchers.runCurrent()
testCoroutineDispatchers.advanceTimeBy(foregroundCpuLoggingTimePeriodMillis)
testCoroutineDispatchers.advanceTimeBy(TimeUnit.MINUTES.toMillis(1))
applicationLifecycleObserver.onAppInBackground()
testCoroutineDispatchers.runCurrent()
testCoroutineDispatchers.advanceTimeBy(backgroundCpuLoggingTimePeriodMillis)

val count = fakePerformanceMetricsEventLogger.getPerformanceMetricsEventListCount()
val events = fakePerformanceMetricsEventLogger.getMostRecentPerformanceMetricsEvents(count)

assertThat(count).isEqualTo(3)
assertThat(events[0].currentScreen).isEqualTo(ScreenName.FOREGROUND_SCREEN)
assertThat(events[1].currentScreen).isEqualTo(ScreenName.FOREGROUND_SCREEN)
assertThat(events[2].currentScreen).isEqualTo(ScreenName.BACKGROUND_SCREEN)
}

@Test
fun testSnapshotter_onCreate_setsIconificationToBgAfterCutOff_logsCpuInBgAfterCorrectDelay() {
applicationLifecycleObserver.onCreate()
testCoroutineDispatchers.runCurrent()
// clearing up all app startup performance metrics: apk size and storage usage.
fakePerformanceMetricsEventLogger.clearAllPerformanceMetricsEvents()
testCoroutineDispatchers.advanceTimeBy(initialIconificationCutOffTimePeriodMillis)
testCoroutineDispatchers.advanceTimeBy(backgroundCpuLoggingTimePeriodMillis)

val count = fakePerformanceMetricsEventLogger.getPerformanceMetricsEventListCount()
val events = fakePerformanceMetricsEventLogger.getMostRecentPerformanceMetricsEvents(count)

assertThat(count).isEqualTo(1)
assertThat(events[0].currentScreen).isEqualTo(ScreenName.BACKGROUND_SCREEN)
}

@Test
fun testSnapshotter_onCreate_setsIconToBgAfterCutOff_moveToFgAndLogsCpuInBg_logsCpuInFg() {
applicationLifecycleObserver.onCreate()
testCoroutineDispatchers.runCurrent()
// clearing up all app startup performance metrics: apk size and storage usage.
fakePerformanceMetricsEventLogger.clearAllPerformanceMetricsEvents()
testCoroutineDispatchers.advanceTimeBy(TimeUnit.MINUTES.toMillis(5))
applicationLifecycleObserver.onAppInForeground()
testCoroutineDispatchers.runCurrent()
testCoroutineDispatchers.advanceTimeBy(foregroundCpuLoggingTimePeriodMillis)

val count = fakePerformanceMetricsEventLogger.getPerformanceMetricsEventListCount()
val events = fakePerformanceMetricsEventLogger.getMostRecentPerformanceMetricsEvents(count)

assertThat(count).isEqualTo(2)
assertThat(events[0].currentScreen).isEqualTo(ScreenName.BACKGROUND_SCREEN)
assertThat(events[1].currentScreen).isEqualTo(ScreenName.FOREGROUND_SCREEN)
}

@Test
fun testSnapshotter_setsIconToBgAfterCutOff_logsCpuInBg_moveToFgAndLogsCpuInBg_logsCpuInFg() {
applicationLifecycleObserver.onCreate()
testCoroutineDispatchers.runCurrent()
// clearing up all app startup performance metrics: apk size and storage usage.
fakePerformanceMetricsEventLogger.clearAllPerformanceMetricsEvents()
testCoroutineDispatchers.advanceTimeBy(backgroundCpuLoggingTimePeriodMillis)
testCoroutineDispatchers.advanceTimeBy(TimeUnit.MINUTES.toMillis(3))
applicationLifecycleObserver.onAppInForeground()
testCoroutineDispatchers.runCurrent()
testCoroutineDispatchers.advanceTimeBy(foregroundCpuLoggingTimePeriodMillis)

val count = fakePerformanceMetricsEventLogger.getPerformanceMetricsEventListCount()
val events = fakePerformanceMetricsEventLogger.getMostRecentPerformanceMetricsEvents(count)

assertThat(count).isEqualTo(3)
assertThat(events[0].currentScreen).isEqualTo(ScreenName.BACKGROUND_SCREEN)
assertThat(events[1].currentScreen).isEqualTo(ScreenName.BACKGROUND_SCREEN)
assertThat(events[2].currentScreen).isEqualTo(ScreenName.FOREGROUND_SCREEN)
}

private fun setUpTestApplicationComponent() {
ApplicationProvider.getApplicationContext<TestApplication>().inject(this)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ interface PerformanceMetricsAssessor {

/** Represents the different states of the application. */
enum class AppIconification {
/** Indicates that the iconification hasn't been initialized yet. */
UNINITIALIZED,
/** Indicates that the app is in foreground. */
APP_IN_FOREGROUND,
/** Indicates that the app is in background. */
Expand Down