The description for the method uptimeMillis says:
Returns milliseconds since boot, not
counting time spent in deep sleep.
Note: This value may get reset
occasionally (before it would
otherwise wrap around).
How often might this happen and (more importantly) will it affect runnables that should be executed by Handler.postAtTime?
The uptimeMillis call grounds out in systemTime(), which on a Linux system turns into clock_gettime(CLOCK_MONOTONIC, struct timespec *).
The struct timespec holds seconds in a time_t, which appears to be a 32-bit value. If it starts counting near zero, you will not likely be alive when it wraps.
If you need more specific details, you should investigate the behavior of clock_gettime(CLOCK_MONOTONIC) in the Linux kernel.
If you happened to call uptimeMillis right when it wrapped, then yes it would affect your postAtTime call.
A signed long in Java has the range:
-9,223,372,036,854,775,807 to 9,223,372,036,854,775,807 (~9.2E18)
9.2E18 milliseconds is 292,277,266 years. If you are working on a space probe, you probably want to take this into consideration, otherwise you can probably get away with assuming it won't wrap in your lifetime.
The kicker for me is that the Android documentation for uptimeMillis claims
This clock is guaranteed to be
monotonic . . .
Then soon after they say that uptimeMillis will be reset due to variable wrapping - the exact opposite of a monotonic clock!
I was using it for a service and did not ever see it resetting. I would really assume it won't.
The problem with postAtTime() is that it will not be called during sleep (since uptimeMillis() will not update). If that's an issue, then I would use some other method.
Related
I do not know why but i created a thread where i am using Thread.sleep(1000) and its working in 8 out of 10 devices but not working in rest 2 devices.
Not working means, thread is sleeping for around 0.5 sec instead of 1 sec and i can see it in logs.
So there is no guarantee that thread will sleep for exact amount of time ?
What could be the possible issues ?
Same code is working in almost devices.
There is no guarantee that Thread.sleep will sleep for an exact amount of time. What the javadoc actually says is:
"Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers."
Sleeping longer than expected it not unexpected. For example, it can happen if the device's cores are all busy doing other things when the "sleep" is due to end.
However, a sleep() call returning significantly sooner than requested sleep time is not expected behavior.
I suspect that the real cause is:
Your thread is getting an interrupt and your code is squashing the exception ... so you don't notice it. An interrupt send to a sleeping thread will cause the sleep call to return early.
Your sleep call's argument is different to what you think.
Possibly a system clock adjustment happened at the wrong time ... though I would expect this to be a "once in a blue moon" event.
This is an artifact of an emulator, a debugger or something like that "messing" with the clock.
However, if this is a real effect and not caused by something that you are doing, then I would say that it is a candidate for reporting as a bug to the vendor of the device. But you would need a way to demonstrate the problem repeatably; i.e. a minimal reproducible example to include in your bug report.
The sleep() documentation warns that it's not precise:
https://developer.android.com/reference/java/lang/Thread#sleep%28long%29
Causes the currently executing thread to sleep (temporarily cease
execution) for the specified number of milliseconds, subject to the
precision and accuracy of system timers and schedulers. The thread
does not lose ownership of any monitors.
public static void sleep (long time)
This is from android docs in Eclipse;
"Causes the thread which sent this message to sleep for the given interval of time (given in milliseconds). The precision is not guaranteed - the Thread may sleep more or less than requested."
What does it mean thread may sleep more or less than requested. Why it is not absolute while working with this method?
It is not absolute for several reasons, the main one being that we can't measure time all that accurately. Also, it may have to wait for more high priority threads to ease up before it is allowed to cut in again.
This problem is not specific to Android, but to any thread in general even on desktop computers, and the reasons are explained very well over here.
According to Android Developer Reference uptimeMillis() returns the number of milliseconds since boot, not counting time spent in deep sleep. I checked the implementation of
uptimeMillis() in my code and it is roughly like this-
struct timespec t;
t.tv_sec = t.tv_nsec = 0;
clock_gettime(CLOCK_MONOTONIC, &t);
return (int64_t)(t.tv_sec)*1000000000LL + t.tv_nsec;
As far as I know CLOCK_MONOTONIC counts from some unspecified point linearly including sleep time.
Here are my doubts-
If CLOCK_MONOTONIC includes sleep time, how come uptimeMillis() doesn't take it into account? If my understanding is wrong and CLOCK_MONOTONIC doesn't take sleep into account, then what should I use to get system uptime including sleep?
What is deep sleep? Is the CPU idling referred as deep sleep?
What is the value of unspecified point in Linux? Can you kindly point out in code where this clock is started?
CLOCK_MONOTONIC stops when the system is suspended. Some people felt this was a mistake, and subsequently there have been patches for adding a CLOCK_BOOTTIME clock: https://lwn.net/Articles/428176/ . I don't know if these patches have yet been included in the mainline kernel. CLOCK_BOOTTIME is in ndk-9c - it only took 2,5 years ;) – Wojciech
Suspend, I guess.
IIRC some fixed time before boot. You'll find the exact value if you dig into the kernel source. Then again, the entire point about it being unspecified is that it could change at any point, so relying on it seems unwise to me.
I'm writing a sports app that needs to track the elapsed time of quarter/half/period. Elapsed time needs to be accurate to the second. The game clock needs to continue to run even if the user explicitly places the device in sleep mode by pressing the power button.
My first attempt at this involved using Handler.postDelayed() to trigger the clock ticks every 200ms and WindowManager.LayoutParms.FLAG_KEEP_SCREEN_ON to ensure that the "clock" wasn't stopped by a screen timeout. But I soon learned that it was possible to circumvent this approach by pressing the power button to manually put the device to sleep. In addition, the postDelayed() approach is experiencing some clock drift, apparently a result of the time spent in the run() method. The actual numbers are still accurate, but instead of being aligned, for example, on 5 second boundaries which are easily understood by users - the timers involved start to drift, resulting in some understandable user confusion.
After a bit of research I found techiques for using services, java timers, AlarmManager, and PartialWakeLock to implement timers. Services by themselves won't solve the problem associated with the device going to sleep. Java timers, like services, don't solve the problem with the device going to sleep. AlarmManager seems like a good approach, but I'm concerned that this isn't an appropriate use of AlarmManager (i.e., very short intervals between alarms). Using PartialWakeLock also looks promising, but by itself it doesn't address the clock-drift problem I'm experiencing.
I'm going to try a combination of AlarmManager and PartialWakeLock. The idea is that AlarmManager will help combat clock-drift and PartialWakeLock to help keep the code simple (fingers-crossed). I'm hoping that this approach will result in a reasonable balance between power conservation, code complexity, and user expectations. Any advice is greatly appreciated.
Thanks,
Rich
I've got a partial solution to my original post above. It doesn't yet address the clock drift associated with the time spent in calculations during the postDelayed() processing, but it is a step forward. In addition, it's deceptively simple, always a good sign.
It turns out I was using SystemClock.uptimeMillis() when I should have been using SystemClock.elapsedRealtime(). The difference between the 2 is subtle, but important.
As you might expect, my solution keeps track of elapsed time by accumulating durations between calls to postDelayed() - i.e., elapsed time = elapsedTime + lastClockInterval. As stated above, the original implementation used uptimeMillis(). Careful reading of the javadoc reveals that uptimeMillis() doesn't include time spent in "deep sleep", e.g., when the user presses the power button. But the elapsedRealtime() method does include time spent in "deep sleep" mode. All that was required to track time across deep sleep cycles was to replace the use of uptimeMillis() with elapsedRealtime(). Success! No need to use AlarmManager, PartialWakeLock, or anything else substantially more complicated. Granted, these methods still have uses, but they are overkill when implementing a simple elapsed-time clock or timer.
The next problem to tackle is with the clock-drift caused by the non-zero execution time associated with postDelayed() processing. I'm hoping that spawning a thread to do the processing will address this issue, allowing postDelayed() to more or less mimic an asynchronous call. Another approach would be to adjust the postDelayed() delay time to take into account the time spent in postDelayed(). I'll post my results.
On an unrelated note, during my investigation I treated myself to a CommonsWare Warescription. While I didn't directly use any ideas from this source for this problem, I do think that it is going to be my Android go-to information source for the foreseeable future. I've got an O'Reilly subscription through my day job, but I've found the CommonsWare books to be as least as good, if not better, source of information about Android development as the O'Reilly resources. And I have found the O'Reilly Safari resources to be pretty good. Interesting...
Cheers,
Rich
I'm sorry this is not quite an answer, but I feel your process is similar to mine, but there was little in regards to code to make it clear how you got around the sleep issue. I don't have drift, but the app does hang when it goes into sleep mode,then kind of resets forward when the display is active, then hangs again when the device sleeps. This is the core of the timer process.
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
// do something here to display
processTime(); // process what to be done on a sec by sec basis
try {
timerHandler.postDelayed(this, 1000
} catch (Exception ex){
}
}
};
Is there something here that I can do to allow it to continue when in sleep mode? This use to work on older version of android/devices.
Hello
In my android application i would like to get Time since when the app is opened.
Initially what i tried was getting the time when the app is loaded from the server and then taking the difference with the current time from the device.But by doing that if the user changes the time then i willnot be getting the actual time.
Its not posiible to hit the server again for the same.
Is there any way to achieve this in android?
Please share your valuable suggestions.
Thanks in advance:)
Try the "SystemClock" class, "uptimeMillis()" method.
Store the result in a variable when the app starts.
Echoing what I said for your other question, you first need to become familiar with the activity lifecycle and understand the novel meanings (almost meaninglessness) of common words like "open" and "start" in the life of an android app.
There isn't any way you can prevent the user from changing the system time - you just don't have the right to do that to users. Normally this should be a rare event, unless you do something that makes them want to, such as lock them out of a free version of your app after so many minutes. (However if the phone is on a mobile network, presumably the mobile network occasionally adjusts its time to correct for errors in the device's oscillator, or administrative time changes)
What you can do is check the system time on every entry point to your application. If it ever goes backwards, well... something is going on. If the clock has been set back, you could assume no time between the calls with the negative time difference and resume your time meter from there, at least keeping all the previous used time in your record.
It may be that there are cpu cycle counters which you could query and correlate to system time, but this may be highly device specific and may in fact be resettable. And it may get weird if the cpu frequency is demand throttled.
You might be able to set a countdown timer as a bound on the maximum possible time between entry points at which you could meter. I don't know if these work reliably across system time changes or not - ideally they would. Testing or reading the source will reveal.
Use elapsedRealtime in your onCreate() store it. More reliable.