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

Android: Instant not advancing while the screen is off #71860

Open
Hocuri opened this issue May 3, 2020 · 6 comments
Open

Android: Instant not advancing while the screen is off #71860

Hocuri opened this issue May 3, 2020 · 6 comments
Labels
A-time Area: Time C-bug Category: This is a bug. O-android Operating system: Android T-libs Relevant to the library team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@Hocuri
Copy link

Hocuri commented May 3, 2020

I tried this code on Android:

let now = Instant::now();
// Wait some hours
now.elapsed().as_secs()

I expected to see this happen: Get some hours as a result

Instead, this happened: Got only minutes because the time while the process is sleeping / the app is "dozing" is not counted.

Nice explanation from mbrubeck (https://users.rust-lang.org/t/std-now-with-android/41774):
Instant::now() on Android (and other Linux platforms) is currently implemented using libc::clock_gettime(CLOCK_MONOTONIC) . Apparently this clock does not advance while the CPU is in deep sleep modes ("Doze"). This is also how Android's SystemClock.uptimeMillis method works.

Android also offers a SystemClock.elapsedRealTime method, which seems to be implemented using an Android-specific ioctl . Perhaps it would be possible to migrate the Rust standard library to use this call on Android, if there are no trade-offs in precision.

@Hocuri Hocuri added the C-bug Category: This is a bug. label May 3, 2020
@jonas-schievink jonas-schievink added O-android Operating system: Android T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels May 3, 2020
@nagisa
Copy link
Member

nagisa commented May 3, 2020

Does elapsedRealTime provide guarantees you’d expect from Instant? (Most notably, monotonicity)

@Hocuri
Copy link
Author

Hocuri commented May 4, 2020

Yes.

https://developer.android.com/reference/android/os/SystemClock:

elapsedRealtime() and elapsedRealtimeNanos() return the time since the system was booted, and include deep sleep. This clock is guaranteed to be monotonic, and continues to tick even when the CPU is in power saving modes, so is the recommend basis for general purpose interval timing.

@maxbla
Copy link
Contributor

maxbla commented Oct 10, 2020

Another option here is to wait until the minimum supported version of linux is >= 2.6.39 to use clock_gettime(CLOCK_BOOTTIME). The Documentation makes this look like it would count "dozing".

@notgull
Copy link

notgull commented Sep 22, 2022

With Rust now requiring Linux 3.2, would it be possible to migrate these timers to CLOCK_BOOTTIME?

@link2xt
Copy link

link2xt commented Dec 23, 2023

With Rust now requiring Linux 3.2, would it be possible to migrate these timers to CLOCK_BOOTTIME?
Note that CLOCK_BOOTTIME is supported since Linux 2.6.39 released in 2011: https://lkml.org/lkml/2011/5/19/16

golang however decided against using CLOCK_BOOTTIME for timeouts to avoid all timeouts going off when laptop is taken out of the doze state: golang/go#24595
For Android which resumes out of doze state automatically from time to time this makes less sense, timeouts should actually be triggered if they are used to wait for some external event, e.g. network, or send keepalives.

There is also a reason fix for CLOCK_MONOTONIC got reverted in the Linux kernel - it breaks watchdog timers which are renewed by running processes from time to time and kill the process if watchdog is not advancing:
https://www.spinics.net/lists/linux-tip-commits/msg43709.html
Windows runtime in Go also implemented similar behavior and had to revert it according to the discussion.

So there is a conflict between the needs of network protocol implementations which want to use timeouts to wait for external events and keepalives and all kinds of existing usecases like watchdog timers which should be triggered if CPU was used but the process did not make any progress and got into some busyloop.

Maybe we need new kind of timestamps and new kind of timeouts.

There is a discussion in the go repo started by zx2c4 (known for creating wireguard): golang/go#36141
It turned into an accepted proposal to implement a second kind of timers and timeouts that use CLOCK_BOOTTIME and keep existing timers using CLOCK_MONOTONIC with existing behaivor.

@Hocuri Hocuri changed the title Android: Instant now advancing during Doze; Use SystemClock.elapsedRealTime Android: Instant not advancing during Doze; Use SystemClock.elapsedRealTime Dec 23, 2023
@Hocuri Hocuri changed the title Android: Instant not advancing during Doze; Use SystemClock.elapsedRealTime Android: Instant not advancing while the screen is off Dec 27, 2023
@Hocuri
Copy link
Author

Hocuri commented Dec 27, 2023

I think this is also for T-libs because it is also about the implementation, not just the API? @rustbot label +T-libs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-time Area: Time C-bug Category: This is a bug. O-android Operating system: Android T-libs Relevant to the library team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

8 participants