Improve timer accuracy #235

Merged
brandon.presley merged 1 commits from joseph/Massive:improve_timer_accuracy into master 2024-03-07 23:12:46 +00:00
Contributor

I used 2.31 yesterday at the gym and noticed that sometimes the auto timer countdown would be relatively the same since last time I checked it, when I expected it to be significantly less.
After some testing I noticed that if I added another set, turned phone off and waved it around it worked fine, while if I tuned it off and left it still when I turned it back on the timer might only show a 5 - 10 second decrease even though over a minute had passed.

Unfortunately I have been unable to reproduce this on the android emulator, however I suspect this issue is caused by my phone going into deep sleep when the screen is off and it isn't moving.

The docs here talk more about how postDelayed uses SystemClock.uptimeMillis(), so it waits 1000ms of system uptime, instead of system time. This means it ignores any time spent in deep sleep.

Additionally, postDelayed has around 4-5ms delay in my testing on a debug build on the android emulator, so for a 3:30 minute rest period you end up gaining around 800ms of delay / extra rest time.
By scheduling the time the next Runnable runs as 1000 - millisElapsed % 1000 it means there isn't any slipping of time.

I have tested this mr today and my issues have been fixed, and tested on emulator and it has the correct behavior.

I used 2.31 yesterday at the gym and noticed that sometimes the auto timer countdown would be relatively the same since last time I checked it, when I expected it to be significantly less. After some testing I noticed that if I added another set, turned phone off and waved it around it worked fine, while if I tuned it off and left it still when I turned it back on the timer might only show a 5 - 10 second decrease even though over a minute had passed. Unfortunately I have been unable to reproduce this on the android emulator, however I suspect this issue is caused by my phone going into deep sleep when the screen is off and it isn't moving. The docs [here](https://developer.android.com/reference/android/os/Handler#postDelayed(java.lang.Runnable,%20long)) talk more about how `postDelayed` uses `SystemClock.uptimeMillis()`, so it waits 1000ms of system **uptime**, instead of system **time**. This means it ignores any time spent in deep sleep. Additionally, `postDelayed` has around 4-5ms delay in my testing on a debug build on the android emulator, so for a 3:30 minute rest period you end up gaining around 800ms of delay / extra rest time. By scheduling the time the next `Runnable` runs as `1000 - millisElapsed % 1000` it means there isn't any slipping of time. I have tested this mr today and my issues have been fixed, and tested on emulator and it has the correct behavior.
joseph added 1 commit 2024-03-07 17:51:58 +00:00

What about CountdownTimer https://developer.android.com/reference/android/os/CountDownTimer any idea if that one works better for second by second updates? What about the system clock app on android do you know what that uses?

Weird to hear its happening on yours because on my device it doesn't pause at all. I'm on a pixel 5 by the way and I've compared its speed to the system clock app and it was identical with the screen off, on, battery saver, everything.

What about CountdownTimer https://developer.android.com/reference/android/os/CountDownTimer any idea if that one works better for second by second updates? What about the system clock app on android do you know what that uses? Weird to hear its happening on yours because on my device it doesn't pause at all. I'm on a pixel 5 by the way and I've compared its speed to the system clock app and it was identical with the screen off, on, battery saver, everything.

You were right King thanks for the fix. I must have been pissing around spending way too much time resting for weeks now...
Not sure how it worked the first few times i tested it but I suppose it's finnicky with the android system time.

You were right King thanks for the fix. I must have been pissing around spending way too much time resting for weeks now... Not sure how it worked the first few times i tested it but I suppose it's finnicky with the android system time.
brandon.presley merged commit 745f9fb046 into master 2024-03-07 23:12:46 +00:00
Author
Contributor

Are you on android 14? because I tested it on another device on A13 (though not for very long) and everything worked fine, but showed issues only on A14 on that same device.

The mr fixes the issue with postDelayed (so a seconds or so out at most), however after further testing I don't think it fully fixes the fact that the Runnable stops running when the phone is in deep sleep. So right now as long as you turn the screen on just before the alarm is scheduled to go off and keep it on - you're good, but if you leave it off planning on waiting for the alarm to go off, you may be waiting longer than expected (in the order of minutes).

Regarding not being able to reproduce on the emulator, I am pretty sure its impossible to get it into deep sleep / doze, as it would claim to be in it, but I could see on the screen that it wasn't.

CountDownTimer looks interesting however the system clock app on android schedules a PendingIntent with the AlarmManager, so I might have a go trying to implement that, as I know that the timers on both phones from the system clock app do work as expected.

Are you on android 14? because I tested it on another device on A13 (though not for very long) and everything worked fine, but showed issues only on A14 on that same device. The mr fixes the issue with `postDelayed` (so a seconds or so out at most), however after further testing I don't think it fully fixes the fact that the `Runnable` stops running when the phone is in deep sleep. So right now as long as you turn the screen on just before the alarm is scheduled to go off and keep it on - you're good, but if you leave it off planning on waiting for the alarm to go off, you may be waiting longer than expected (in the order of minutes). Regarding not being able to reproduce on the emulator, I am pretty sure its impossible to get it into deep sleep / doze, as it would claim to be in it, but I could see on the screen that it wasn't. `CountDownTimer` looks interesting however the system clock app on android schedules a `PendingIntent` with the `AlarmManager`, so I might have a go trying to implement that, as I know that the timers on both phones from the system clock app do work as expected.

I believe AlarmManager doesn't allow for setting things to go off faster than like 15 minutes into the future. How does the system clock use it for every second?

I believe AlarmManager doesn't allow for setting things to go off faster than like 15 minutes into the future. How does the system clock use it for every second?
brandon.presley deleted branch improve_timer_accuracy 2024-03-08 00:18:06 +00:00
Author
Contributor

I don't think there is a 15 minute restriction on them. In the docs it talks about 15 minute minimum for WorkManager as an alternative for AlarmManager.
Or how there could be up to a 15 minute delay when in low-power idle modes for a certain function setExactAndAllowWhileIdle.

The clock app does something similar, using postDelayed to update second by second here. However it is not responsible for triggering the alarm when the time has elapsed.

It uses AlarmManager to schedule and trigger the alarm, see here.

By scheduling with the alarm manager what should happen is that the alarm should go off at the time regardless of what postDelayed is doing.

I don't think there is a 15 minute restriction on them. In the docs it talks about 15 minute minimum for `WorkManager` as an alternative for `AlarmManager`. Or how there could be up to a 15 minute delay when in low-power idle modes for a certain function `setExactAndAllowWhileIdle`. The clock app does something similar, using `postDelayed` to update second by second [here](https://github.com/LineageOS/android_packages_apps_DeskClock/blob/56617759ab423cc57021869a0d2f4b7346b7b1ae/src/com/android/deskclock/timer/TimerFragment.java#L521). However it is not responsible for triggering the alarm when the time has elapsed. It uses `AlarmManager` to schedule and trigger the alarm, see [here](https://github.com/LineageOS/android_packages_apps_DeskClock/blob/56617759ab423cc57021869a0d2f4b7346b7b1ae/src/com/android/deskclock/data/TimerModel.java#L693). By scheduling with the alarm manager what should happen is that the alarm should go off at the time regardless of what `postDelayed` is doing.
Sign in to join this conversation.
No reviewers
No Milestone
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: brandon.presley/Massive#235
No description provided.