1 /* 2 * Copyright 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.compose.runtime 18 19 /** 20 * A [MonotonicFrameClock] wrapper that can be [pause]d and [resume]d. 21 * 22 * A paused clock will not dispatch [withFrameNanos] events until it is resumed. Pausing a clock 23 * does **not** stop or change the frame times reported to [withFrameNanos] calls; the clock times 24 * reported will always remain consistent with [frameClock]. 25 * 26 * [PausableMonotonicFrameClock] should be used in cases where frames should not be produced under 27 * some conditions, such as when a window hosting a UI is not currently visible. As clock times are 28 * not altered from the source [frameClock], animations in progress may be fully complete by the 29 * time the clock is resumed and a new frame is produced. 30 */ 31 class PausableMonotonicFrameClock(private val frameClock: MonotonicFrameClock) : 32 MonotonicFrameClock { 33 private val latch = Latch() 34 35 /** 36 * `true` if this clock is currently [paused][pause] or `false` if this clock is currently 37 * [resumed][resume]. A PausableMonotonicFrameClock is not paused at construction time. 38 */ 39 val isPaused: Boolean 40 get() = !latch.isOpen 41 42 /** 43 * Pause the generation of frames. Pausing a clock that is already paused has no effect. While 44 * the clock is paused any calls to [withFrameNanos] will suspend until the clock is resumed 45 * before delegating to the wrapped [frameClock]'s [withFrameNanos] method. Call [resume] to 46 * resume generating frames. 47 */ pausenull48 fun pause() { 49 latch.closeLatch() 50 } 51 52 /** 53 * Resume the generation of frames. Any queued calls to [withFrameNanos] will resume and 54 * delegate to the wrapped [frameClock]'s [withFrameNanos] method. 55 */ resumenull56 fun resume() { 57 latch.openLatch() 58 } 59 withFrameNanosnull60 override suspend fun <R> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R): R { 61 latch.await() 62 return frameClock.withFrameNanos(onFrame) 63 } 64 } 65