Different values for nano time in different sensor data. How to figure them out?
Asked Answered
S

1

10

Since the latest Android update (v. 8), I realized a very strange behavior while trying to read sensors. More specifically, I am speaking about WiFi and Cell Towers. Here are two examples:

While I read WiFi access point information data and try to convert accessPoint.timestamp to an absolute timestamp using this code:

long timeInMillis = System.currentTimeMillis() + ((accessPoint.timestamp * 1000L -
                SystemClock.elapsedRealtimeNanos()) / 1000000L);

However, the same code does not work properly when I read Cell Towers using nearbyCellTowers = mTelephonyManager.getAllCellInfo(); and I have to use this other code:

long timeInMillis = System.currentTimeMillis() + ((gsmRecord.getTimeStamp() -
                    System.nanoTime()) / 1000000L);

If you did not notice the difference, it is in using either SystemClock.elapsedRealtimeNanos() or System.nanoTime().

According to Android documentation getTimeStamp() is:

getTimeStamp(): Approximate time of this cell information in nanos since boot

A similar for WiFi:

timestamp: timestamp in microseconds (since boot) when this result was last seen.

While the descriptions seem identical (time since boot), but the values are totally different. As you can see, WiFi timestamp is comparable to the value of SystemClock.elapsedRealtimeNanos(), while CellInfo timestamp is comparable to System.nanoTime().

I can never say which one would work with which of the two functions unless I debug and look at the results. Am I missing something here? Can someone clarify this for me? What is the main difference between these two functions and why the two timestamps with the same description have different values?

Stripy answered 28/12, 2017 at 19:51 Comment(2)
Hallo! Were you able to fix this issue in any way on all platforms? I mean, from my understanding, simply using System.nanoTime would break older Android versions. And if we want to use different methods on different Android versions, we need to know specifically what versions of Android behave in which way. Or is it vendor-specific?Jerroldjerroll
@Jerroldjerroll If possible provide your test results.Nummulite
F
3

ScanResult#timestamp and CellInfo#getTimeStamp() is not same. It is pretty clear from the doc.

ScanResult#timestamp

timestamp in microseconds (since boot) when this result was last seen.

I think the word "Since boot" is the one which confuses you. It means the timer will reset when system reboots (and it never means the timer starts when system boots).

CellInfo#getTimeStamp()

Approximate time of this cell information in nanos since boot

Like the previous one, the timer will reset on reboot.


WiFi timestamp is comparable to the value of SystemClock.elapsedRealtimeNanos(), while CellInfo timestamp is comparable to System.nanoTime().

I think you mean "compatible" by "comparable". There is no compatibility issue here. Both SystemClock.elapsedRealtimeNanos() and System.nanoTime()are representation of time as nano seconds.

System.nanoTime()

Returns the current value of the running Java Virtual Machine's high-resolution time source, in nanoseconds. It stops in deep sleep

SystemClock.elapsedRealtimeNanos()

Returns nanoseconds since boot. It will continue to tic even in sleep.




Finally to FreeNickname's question:

From my understanding, simply using System.nanoTime would break older Android versions. And if we want to use different methods on different Android versions, we need to know specifically what versions of Android behave in which way. Or is it vendor-specific?

You can use SystemClock#elapsedRealtime() in all versions of Android. It is introduced in API level 1. Note that unlike elapsedRealtimeNanos(), it returns milliseconds.

Featly answered 29/7, 2018 at 11:52 Comment(4)
Thanks, Anees! I'm not sure I understand though. It means the timer will reset when system reboots (and it never means the timer starts when system boots) In this case there should be a method to get the connection time (to transform this counter to a timestamp). Besides, the device may never connect to wifis from the ScanResult, because it refers to a list of all access points around, not the access point that the device is connected to. Could you provide sources for this statement, please? ` timer initiates when the device is started to receive cell signal` for this statement, too.Jerroldjerroll
You can use SystemClock#elapsedRealtime() in all versions of Android. It is introduced in API level 1. Note that unlike elapsedRealtimeNanos(), it returns milliseconds. – that's understood. What I mean is that it looks like we're supposed to use different reference points to convert the "timestamps" in question into unix timestamps. And in some cases we need to use one method, and in other cases – another.Jerroldjerroll
@Jerroldjerroll thanks for pointing it out. I guess I was wrong about when do those times starts. I was just trying to explain what "Since boot" means here. Now to the second point, I am not sure about this but to the best of my knowledge, both the methods returns the same type of timestamps. If you want to make it UNIX-like, you can do it like (timeInNanos/1000000)Featly
Here's my concern: timestamp is a timestamp. The timer doesn't "start". A timestamp is just a number of (mili|micro|nano)seconds since some reference point. And it's not clear from the docs, which reference point we should use for ScanResult#timestamp: nanoTime or elapsedRealtimeNanos. It may also be that the implementation changed at some point from one reference point to the other (I don't remember where I took that from at the moment, though).Jerroldjerroll

© 2022 - 2024 — McMap. All rights reserved.