Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -214,16 +214,12 @@ internal class ComposeSceneMediator(

private val isActive get() = coroutineContext.isActive

private var isPrefetchVoteActive: Boolean = false // TODO CMP-10587: Move inside the IosPrefetchScheduler
private val prefetchScheduler = IosPrefetchScheduler(
onHasWorkScheduled = { hasWork ->
if (hasWork != isPrefetchVoteActive) {
isPrefetchVoteActive = hasWork
if (hasWork) {
activitiesHandler.onActivitiesStarted()
} else {
activitiesHandler.onActivitiesEnded()
}
onPrefetchVoteChanged = { isVoteActive ->
if (isVoteActive) {
activitiesHandler.onActivitiesStarted()
} else {
activitiesHandler.onActivitiesEnded()
}
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,19 @@ import platform.QuartzCore.CACurrentMediaTime

internal class IosPrefetchScheduler(
private val currentTime: () -> NSTimeInterval = { CACurrentMediaTime() },
private var onHasWorkScheduled: (Boolean) -> Unit,
private var onPrefetchVoteChanged: (Boolean) -> Unit,
) : PlatformPrefetchScheduler {
private val scheduledPrefetchRequests = ScheduledPrefetchRequests()
private val scope = PrefetchRequestScopeImpl()
private val hasWorkScheduled: Boolean get() = scheduledPrefetchRequests.hasWorkScheduled

/**
* Whether the scheduler currently votes for prefetch activities to be running.
*
* Tracked here so [onPrefetchVoteChanged] is only invoked when the vote actually changes.
*/
private var isPrefetchVoteActive: Boolean = false

/**
* Marks the start of the display-link interval where drawing happened.
*/
Expand Down Expand Up @@ -73,7 +80,7 @@ internal class IosPrefetchScheduler(
}

scheduledPrefetchRequests.addHighPriority(request)
onHasWorkScheduled(hasWorkScheduled)
updatePrefetchVote(hasWorkScheduled)
}

override fun scheduleLowPriorityPrefetch(request: PlatformPrefetchRequest) {
Expand All @@ -86,7 +93,7 @@ internal class IosPrefetchScheduler(
}

scheduledPrefetchRequests.addLowPriority(request)
onHasWorkScheduled(hasWorkScheduled)
updatePrefetchVote(hasWorkScheduled)
}

/**
Expand All @@ -106,7 +113,7 @@ internal class IosPrefetchScheduler(
"IosPrefetchScheduler.execute() must be called on main thread"
}
if (isDisposed) {
onHasWorkScheduled(false)
updatePrefetchVote(false)
return
}

Expand All @@ -119,7 +126,7 @@ internal class IosPrefetchScheduler(
}

if (!hasWorkScheduled) {
onHasWorkScheduled(false)
updatePrefetchVote(false)
return
}

Expand All @@ -137,7 +144,7 @@ internal class IosPrefetchScheduler(
}
}

onHasWorkScheduled(hasWorkScheduled)
updatePrefetchVote(hasWorkScheduled)
traceValue("compose:lazy:prefetch:available_time_nanos", 0L)
}

Expand Down Expand Up @@ -166,8 +173,15 @@ internal class IosPrefetchScheduler(
}
isDisposed = true
scheduledPrefetchRequests.clear()
onHasWorkScheduled(false)
onHasWorkScheduled = {}
updatePrefetchVote(false)
onPrefetchVoteChanged = {}
}

private fun updatePrefetchVote(hasWork: Boolean) {
if (hasWork != isPrefetchVoteActive) {
isPrefetchVoteActive = hasWork
onPrefetchVoteChanged(hasWork)
}
}

private fun executeRequest(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,34 +91,46 @@ class PlatformPrefetchSchedulerTest {
}

@Test
fun testReportsNoScheduledWorkWhenNoRequestsAreScheduledAndDidNotDraw() {
val hasWorkEvents = mutableListOf<Boolean>()
val scheduler = scheduler(onHasWorkScheduled = hasWorkEvents::add)
fun testDoesNotVoteForPrefetchWhenNoRequestsAreScheduledAndDidNotDraw() {
val prefetchVoteEvents = mutableListOf<Boolean>()
val scheduler = scheduler(onPrefetchVoteChanged = prefetchVoteEvents::add)

scheduler.execute(lastFrameTimestamp = 0.0, targetTimestamp = 1.0, didDraw = false)

assertEquals(listOf(false), hasWorkEvents)
assertTrue(prefetchVoteEvents.isEmpty())
}

@Test
fun testReportsNoScheduledWorkWhenNoRequestsAreScheduledAndDidDraw() {
val hasWorkEvents = mutableListOf<Boolean>()
val scheduler = scheduler(onHasWorkScheduled = hasWorkEvents::add)
fun testDoesNotVoteForPrefetchWhenNoRequestsAreScheduledAndDidDraw() {
val prefetchVoteEvents = mutableListOf<Boolean>()
val scheduler = scheduler(onPrefetchVoteChanged = prefetchVoteEvents::add)

scheduler.execute(lastFrameTimestamp = 0.0, targetTimestamp = 1.0, didDraw = true)

assertEquals(listOf(false), hasWorkEvents)
assertTrue(prefetchVoteEvents.isEmpty())
}

@Test
fun testReportsNoScheduledWorkWhenQueueDrains() {
val hasWorkEvents = mutableListOf<Boolean>()
val scheduler = scheduler(onHasWorkScheduled = hasWorkEvents::add)
fun testVotesForPrefetchWhileWorkIsScheduledAndEndsWhenQueueDrains() {
val prefetchVoteEvents = mutableListOf<Boolean>()
val scheduler = scheduler(onPrefetchVoteChanged = prefetchVoteEvents::add)

scheduler.scheduleLowPriorityPrefetch(request("request"))
scheduler.execute(lastFrameTimestamp = 0.0, targetTimestamp = 1.0, didDraw = false)

assertEquals(listOf(true, false), hasWorkEvents)
assertEquals(listOf(true, false), prefetchVoteEvents)
}

@Test
fun testDoesNotEmitDuplicatePrefetchVotes() {
val prefetchVoteEvents = mutableListOf<Boolean>()
val scheduler = scheduler(onPrefetchVoteChanged = prefetchVoteEvents::add)

scheduler.scheduleLowPriorityPrefetch(request("request-0"))
scheduler.scheduleLowPriorityPrefetch(request("request-1"))
scheduler.execute(lastFrameTimestamp = 0.0, targetTimestamp = 1.0, didDraw = false)

assertEquals(listOf(true, false), prefetchVoteEvents)
}

@Test
Expand Down Expand Up @@ -169,10 +181,10 @@ class PlatformPrefetchSchedulerTest {
}

private fun scheduler(
onHasWorkScheduled: (Boolean) -> Unit = {},
onPrefetchVoteChanged: (Boolean) -> Unit = {},
currentTime: () -> NSTimeInterval = { 0.0 },
) = IosPrefetchScheduler(
onHasWorkScheduled = onHasWorkScheduled,
onPrefetchVoteChanged = onPrefetchVoteChanged,
currentTime = currentTime,
)

Expand Down
Loading