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

Getting an old location #13

Open
sim6 opened this issue Aug 14, 2015 · 19 comments
Open

Getting an old location #13

sim6 opened this issue Aug 14, 2015 · 19 comments

Comments

@sim6
Copy link

sim6 commented Aug 14, 2015

Firstly thanks for your work.

I use de f-droid build on my FairPhone1. When I loose the GPS signal then I recieve an old location.

@mvglasow
Copy link

Same here. Steps to reproduce:

  1. Move to an area that is mapped.
  2. Start an app that queries network location, e.g. SatStat or Navit R6338 or higher (the latest version on F-Droid should work). Verify that your correct position is shown and that it is from the NLP, not from GPS. (In Navit, the location should show almost instantly and before you have a GPS fix. In SatStat, look for the blue marker on the map.)
  3. Stop the app (in the case of Navit, choose "Exit Navit" or "Quit"), making sure the location icon disappears from the system status bar.
  4. Move to a different location, with no GPS coverage and no mapped wifis nearby, possibly also not served by any mapped cell. (An underground station works well.)
  5. Start the app again and check your location. (In my case 17 minutes elapsed between the two location checks.)

The app will show the old location and report it as current. Adding some debug log output to the receiving app I could clearly see that the Location returned has a current timestamp, which is increased every 4–5 seconds. The NLP is clearly lying here, taking a location calculated 17 minutes earlier and reporting it as current and accurate.

Suggested fixes:

  • The timestamp should be calculated and stored when a wifi scan completes or cell information is obtained. This is the timestamp which locations should report, and no other code should alter it – a location is as old as the scan results behind it, and nothing (other than fresh data) can rejuvenate it.
  • When a new scan result is ready (even an empty one), discard the old location based on the previous one. If the new scan result does not contain any known wifis, we can try to fall back to cell location, and failing that, we simply don't know where we are and should not be sending out locations at all.
  • report() probably should be called just once, right after a new scan result has been received and calculation has finished. That will send the location to all apps which are currently listening, and it is up to them to deal with the update interval. This might increase the time until apps see the first location (if an app is unlucky enough to register just after the last update), but that can be countered by increasing the refresh interval (probably not an issue with the offline DB, in online mode the pros and cons should be balanced). Side question: does anyone use GAPPS and knows what their refresh interval is?

Attaching a logcat of my attempts. I got the correct location at 23:59 and a stale one at 0:16. Tests were conducted with a non-official build of Navit, which has some extra debug output to reveal the timestamps.

alogcat.2015-11-26-00-16-58+0100.txt

@wish7code
Copy link
Member

Hey Simó, hey Michael,

thanks to both of you for reporting. Michael, your logcat is very helpful on this:

The strange thing here: Have a look at 23:59, when you had mapped wifis around:

11-25 23:59:49.191 V/NlpLocationBackendFuser( 1566): location= ... {Bundle[{bssids=[c8:0e:14:00:22:9c, c8:0e:14:06:59:12, c8:0e:14:06:59:13, 00:a0:57:24:40:e1, cc:03:fa:e4:a5:a0, ...

16 min later, when you had no known wifis around the location provider still sees exactly the same previous wifis..

11-26 00:16:38.927 V/NlpLocationBackendFuser( 1566): location=... {Bundle[{bssids=[c8:0e:14:00:22:9c, c8:0e:14:06:59:12, c8:0e:14:06:59:13, 00:a0:57:24:40:e1, cc:03:fa:e4:a5:a0, ...

I still don't see the code path, which pulls in the this outdated scan results

https://github.com/wish7code/org.openbmap.unifiedNlpProvider/blob/master/src/org/openbmap/unifiedNlp/services/OpenbmapNlpService.java#L209
uses the LATEST (possibly outdated) scan results, but it's only called if system signals NEW scan results available, so this shouldn't be an issue at all.

In the meantime, I was wondering whether you could 'Activate debug messages' in openbmap unified net location provider backend to get more verbose logging?

Cheers
Toby

@mvglasow
Copy link

Hi Toby,

Yes, I've seen those wifi lists as well, didn't look into them in detail but realized they looked similar. My suspicion was that the backend reuses the previous scan result.

I visited the same place again yesterday at 17:14 and scanned with SatStat. Initially it showed me a list of wifis from my previous location (again some 15 minutes old), then it refreshed. There was only one wifi in range, which appeared to be a cell phone. The serving cell was mcc=262 mnc=02 lac=953 cid=246275412 psc=216, no other cells in range. Despite the current wifi list, the map view still had the old location reported as current.

I can't tell if there were any wifis in range when I collected the logcat. However, given that I saw only one wifi during peak hours and the logcat was collected at a less busy time, there's a good chance there weren't any wifis in sight.

Debug messages are activated (the check mark was set and I didn't change any settings recently), so the logcat was almost certainly taken with that setting enabled – in fact I see some debug messages in it that would have been suppressed otherwise.

Lines 965/966 show that OpenbmapNlpService.onLocationReceived() is getting called and passed a Location with the old list of wifis in the extras. That rules out the UniversalNLP framework as the culprit – the update was sent by the backend. Either there's some bug in the backend which causes it to reuse stale scan results or stale locations – or my phone returns stale WiFi scan results.

As for the latter possibility, the SatStat screen shows me a stale list for about a second (which is the interval after which SatStat will trigger a new scan) but then updates it. If the phone really is the culprit, it would mean it first returns a stale scan result. A second later a current scan result arrives, but since that results in a location some 3 km away, it fails the plausibility check and is discarded. (Question – would I see that in the log files?) I can't really rule this out, but the fact that I see four calls to OpenbmapNlpService.onLocationReceived() with a stale location/wifi list indicates the issue is likely somewhere else.

wish7code added a commit that referenced this issue Nov 28, 2015
…ager.WIFI_MODE_SCAN_ONLY) to prevent wifi go to sleep mode
@wish7code
Copy link
Member

Might also be related to the wifi sleep mode (e.g. see the discussion at http://stackoverflow.com/questions/14862018/startscan-has-result-after-10-min-when-phone-get-into-idle-state/14910918#14910918)

I added a WIFI_MODE_SCAN_ONLY lock and pushed a new version to F-Droid. Let's see whether this helps

@sim6
Copy link
Author

sim6 commented Nov 28, 2015 via email

@mvglasow
Copy link

I'll wait for the F-Droid build, then.

If that doesn't help, maybe you can add some extra debug output. It would be interesting to find out when we get notified of a new scan result.

Also, you might want to take a look at ScanResult.timestamp (http://developer.android.com/reference/android/net/wifi/ScanResult.html#timestamp). It will indicate when the scan result was last seen, so you could examine that (and possibly discard any results which are more than a few seconds old). It requires API 17, though.

@mvglasow
Copy link

It seems F-Droid didn't pick up v0.1.9 yet, thus I'm still on the old version.

In the meantime I've noticed something else: I had been using Navit (a dev build that permanently listens for network location), then stopped it and moved a little further. After a few minutes I checked my location using SatStat. It started up showing the location in which I'd quit Navit, and took a few seconds to detect my new position.

Bottom line: the stale location issue appears to be unrelated to the presence of known wifis (or any wifis at all) at the new location.

It appears that there are two separate issues: first, locations based on old scan results are given out with a new timestamp. Second, the location apparently doesn't get invalidated as the device moves out of the coverage area of any (known?) wifis.

Tests to conduct would be:

  • Is the stale location the last location supplied by the provider, or the location of the last wifi scan? To find out:
    • Start an app that queries network location and stop it after receiving a few locations.
    • Move a few hundred meters.
    • Start Radiobeacon and log for a while.
    • Move a few hundred meters further.
    • Check SatStat or similar: which is the network location it reports? If it is the one in which Radiobeacon was stopped, the issue is that new locations are generated from stale wifi scan results. If it is the one in which the first app was stopped, it means stale locations are given out without even considering later scan results.
  • Using SatStat or similar, move out of the WiFi coverage area, preferably moving a few hundred meters without wifis in range. (A road tunnel would probably work well.) Examine the logcat: what location updates do we get?
@mvglasow
Copy link

Just ran the first of the two tests I described. The stale location is the last location supplied by the provider; subsequent wifi scans by other apps (Radiobeacon) do not affect the location returned.

Unfortunately I did not manage to pull a logcat.

@mvglasow
Copy link

Version 0.1.11 just appeared on F-Droid, I'll repeat the tests and then report.

@mvglasow
Copy link

mvglasow commented Mar 3, 2016

The issue still seems to be there with 0.11.1. I currently don't have a functional wifi catalog – as soon as I do, I will pull a logcat and post it.

@mvglasow
Copy link

It looks like the underlying issue is a different one: Apparently the wifi scan implementation in Android itself is buggy and occasionally returns stale scan results.

While testing out some accuracy improvements, I added code to log a warning for each stale wifi in mvglasow@3e66390. A brief test at my desk reveals that every other set of scan results has one or two (out of about 6) wifis which are more than five seconds old (my threshold), some of them as old as 8 seconds.

I'll have to test how this behaves when I change locations, but I suspect I'll get a bunch of stale wifis.

I intend to file a merge request once I've completed work on my branch. If you are planning on merging it, I'll implement a fix.

The branch I'm working on introduces actual accuracy estimates for each wifi, from which the accuracy estimate for the new location is derived. Accuracy is currently estimated using signal strength as well as "disagreement" between wifis, and position estimates are fused with greater weight given to more accurate individual positions. This has shown to mitigate the effect of a (presumably single) moved wifi quite well. So far I've optimized only the wifi-based part but I am planning to fuse cell-based locations as well.

A similar approach could be applied to stale wifis, penalizing accuracy based on age.

@wish7code
Copy link
Member

The branch I'm working on introduces actual accuracy estimates for each wifi, from which the accuracy estimate for the new location is derived. Accuracy is currently estimated using signal strength as well as "disagreement" between wifis, and position estimates are fused with greater weight given to more accurate individual positions. This has shown to mitigate the effect of a (presumably single) moved wifi quite well. So far I've optimized only the wifi-based part but I am planning to fuse cell-based locations as well.

Sounds terrific! If you got something to merge, I would love to do that!

@mvglasow
Copy link

Great! Bear with me... I've implemented the logic to fuse the serving cell's location. Currently I'm working on penalizing stale wifis. Once this is working, I'll add lookup for neighbor cells (as long as we have the full cell ID – as is the case in GSM networks) and file a merge request.

@mvglasow
Copy link

Ran some tests today, and it looks like we have both lice and fleas.

I fired up SatStat in an environment with known wifis and the modified backend gave me a crisp (+/- 20 m) location. Then I moved to a metro station with no wifis at all, and fired up SatStat again, 5 minutes after leaving the previous location. SatStat claimed I was still within 20 meters of the old location, even after I killed and restarted it (to rule out any caching in SatStat).

Analyzing the logcat, I find that I originally had 26 wifis in range, from which the backend calculated a location and reported it. In the metro station, the backend reported that no wifis were in range and the only visible cell was not in the DB, and subsequently returned a null location. Then, however, UnifiedNLP (specifically NlpLocationBackendFuser) reports the same location it has given out 5 minutes before, with the same et=+15d21h34m50s905ms (which I suppose is the timestamp) and the same accuracy acc=20.

Thus, apparently now the backend does all it can do to avoid giving out stale locations (at least in offline mode): it penalizes stale scan results, fuses cell and wifi locations, and it detects when nothing known is in range and correctly reports a null location in that case. This currently hints at UnifiedNLP as the source of the problem.

@mvglasow
Copy link

I've opened an issue for UnifiedNLP. What isn't quite clear to me: should we call report(null) when we can't determine the location, or should we just not call report() at all? That isn't quite clear in the API docs. I'll see what happens if we skip the call.

@mvglasow
Copy link

Going through the code in detail, I see that report() never gets called if the new location is null.

@mvglasow
Copy link

See the other ticket for details on UnifiedNLP.

As for my branch, cell-based location still needs testing, and I'm also going to add blacklist filtering. When that is complete, I'll file a merge request.

@mvglasow
Copy link

Now that both UnifiedNLP and the openBmap backend have updated versions, things look a lot better.

During my last "tunnel test", however, I fired up SatStat in the middle of the tunnel and got a location at the tunnel entrance, then no more updates until I was out of the tunnel. The logcat revealed this one location to be based on a scan result that was over 30 seconds old, and accuracy reflected that age.

Still I'm wondering: should we introduce a threshold for wifi scan results, discarding scans which are older? With a threshold, we wouldn't get a location at all in situations like these, whereas otherwise we'd get a location like "within 500 m of the portal". IMHO that's the last question to resolve before we can close this ticket.

@gdt
Copy link
Member

gdt commented Mar 27, 2016

It seems that different people will want different things. Some suppressing of old results is just fixing bugs, but since wifi scanning is not continuous, I think there's a legitimate question of the age of a sighting to still let it be used. 5 minutes is obviously (to me) way too old, and 2s is recent enough. I think the big question is when you are in range of only 1 wifi, and the provider is scanning, how frequently do reports happen, and what fraction of reports have the wifi? The age should be chosen to be as short as possible while not failing to provide a location say 99% of the time.

All in all, this makes me think the wifi max age should be a preference setting. Then not only can people play with it easily to find out what's pleasing, but people with different opinions can set it differently. I can see people want to set it to 10 minutes - although presumably that would only happen if the provider were being constantly queried, and perhaps there should be some 100 km/hr error model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
4 participants