Badoo geolocation testing: bumps, stones, crutches and selfie stick
It seems that there are already thousands of materials about testing mobile applications, so it’s hard to surprise here. But while aspects like UI are already jammed to the holes, geolocation testing is much less frequently reported. And when at our conference Heisenbug Nikolai lamamer Kozlov and Alexander z3us Host ( Badoo ) shared their experiences, the audience of the conference was very interested in the report. How to get geolocation, and the phone user does not defuse? Why in this testing stick? How close are London pubs and what follows from this?
We decided that Habr’s audience might also be interesting, and we post it in two versions at once: for fans to watch the video, and for fans to read the text version under the cut.
')
Introduction
Alexander Khozy : Let's first get acquainted. My name is Alexander Host, in the company everyone is called by the name “Host”, I am used to it, you can also contact me like that. I run all the manual mobile testing at Badoo, I don’t like all mobile operating systems about the same, and today I’ll talk about iOS.
Nikolay Kozlov: My name in the company, by the name of “Kozya,” I also got used to it. I love gadgets, especially on the Android operating system and in general Unix-like ones. I don’t like iOS: I have Apple Watch and iPhone only to understand how much I hate their good service and quality of service.
A little about us. Probably, you already know that Badoo is a service for searching for new acquaintances. We have over 360 million users (of which 60 million are active per month), and about 300,000 registrations per day. They generate 350 million messages per day.
As for our report directly. So that you understand the amount of data that our poor servers have to handle: our users generate about two billion coordinates per day. These two billions generate about 10 million "intersections" - we will tell about what intersection is a little bit later.
In this case, everything that we describe below is possible only with test users. We do not have access to real user data, except for the case of checking some anomaly or a bug, and even in this case, the user’s permission for this action is needed.
So, what we talk about today:
How is geolocation useful?
About tools that allow you to save seven kilograms of nerve cells (as you can see by me, saved well)
On energy consumption when using geolocation and its optimization
About why it is necessary to work in the field and go out there
Well, since the conference is about testing, of course, let's talk about bugs
How is geolocation useful?
Let's first remember what geolocation is all about, what it is eaten with, and how it works in modern devices.
Historically, it appeared in iOS with the release of version 2.0 in 2008, and then your phone learned to “calculate by IP”. The problem was that Geo IP gives low accuracy: at best it will be a street, and in the case of a mobile device it is usually a country, because IP addresses are mostly floating (the operator in each region has its own address range, which is often not geographically attached).
In the future, the engineers decided to use the so-called Cell ID. The principle of operation is quite simple: we know the location of the base points in space, and knowing the signal level from these points, we can roughly determine the distance to them. Next we draw a large number of rounds, and somewhere in the overlapping area of all the circles is the user. Accuracy has already increased: in small cities it is 1000 meters, and in cities like Moscow, where there are much more base stations, it is 60 meters. And when using Wi-Fi, Bluetooth and other beacon, you can improve the accuracy up to 10 meters, which is very convenient: do not use the following system, which is called GNSS, or the global navigation satellite system.
Why am I not saying “GPS”? Because in the market of navigation systems there are several players. The main ones are GPS, GLONASS, Chinese BeiDou and European Galileo. In addition, there are two regional navigation systems - the Indian IRNSS and the Japanese QZSS ("Quasi-zenith navigation system"). Why are there so many systems? All dual-use systems, if necessary, in certain cases, you can disable them. Also, some systems are needed to clarify the location, because in India and Japan there is a known displacement of GPS satellites, which need to be calculated all the time, this is an extra headache. The Japanese love accuracy, and after the introduction of QZSS, only two satellites are enough to have an accuracy of at least 10 centimeters at best, and at best one centimeter.
In this case, the main problem of all navigation systems is a cold start. At the device, which has just been released from the factory and has never received geolocation, at the very first launch a cold start without A-GPS will be 15 minutes: 12 and a half minutes it will swing the atlas of the starry sky, and another two and a half minutes will go to receive signals from satellites. This is a big problem, and therefore they came up with the A-GPS system: using Geo IP and Cell ID, the phone quickly determines the approximate location and sends it to a special server that gives the atlas. After 2-3 minutes (in most cases even less), the phone quickly finds satellites, and shows you where you are, very convenient.
Now let's talk about why geolocation is needed. First of all - to personalize content.
If your product is a navigation system and you are not using geolocation, most likely, users will not use it. If you are doing some kind of advertising application, personalization is also possible: you pass by some store, the phone understands this, and a push notification is triggered that right now in this store you have a 50% discount. In the course of dating, geolocation is also very important. Our users want to see those who are in their city, and preferably even as close as possible. And do not want to see users from other countries. With the help of geolocation, we solve this and many other problems.
All the improvements related to geolocation, we have developed for the service "Intersection", which Sasha will tell a little later. I will say only that it was clear how this should work from the point of view of users, logic. But it was completely incomprehensible how to get as many coordinates and geodata as possible with as little power consumption as possible. It was 2014, there was a lot of information on how to implement all this on the client side, but there was absolutely no information on how to test it. Unfortunately, I had to find everything myself, and create the documentation myself from scratch. Now let's talk about where and how we use geolocation.
Host: Our very first main screen is dating, where users vote for each other. As Kolya said earlier, it is much more interesting to find people and communicate when they are near you, therefore geolocation is one of the most important weights, according to which our server issues users to each other.
Our next screen has the saying name “People are nearby”, where in the very first section you see people who are as close as possible to you. Unless, of course, you gave us access to our geolocation services. If not given, we will ask you to enter at least a city. You open user profiles and see that they are near you: let's say Alena was 300 meters away from us.
On the same screen, we just show the intersections, and it is time to tell how it all works. In theory, it is not very difficult: you moved and at a certain moment the trajectories of movement of you and other users either crossed at a particular point, or you were as close as possible to each other (for example, 20 meters). If you intersect with one user, then we generate a personalized push. Check whether you communicated with this user, say, you liked it or corresponded, it added you to your favorites, etc. We send a personalized push, you can open its profile, see that they crossed at about this or that location (approximately, in order to get rid of all sorts of evil radishes that they would like to meet in the gateway). If you crossed at once with 3-4 people, we will land you on the “people nearby” screen, and the users with whom you crossed are marked with a special tick.
You can also share geolocation in a chat or request it, let's say that a user comes up to you: you are in a cafe, sent geolocation, very convenient.
Also, in one of our by-products, geolocation is used for check-ins. In principle, plus or minus Swarm, but about the dating. Suppose you go to the same steakhouse, and you wonder who else goes there to chat about steaks. Either you came to the club, launched the application and see that there are 24 people in the club at the moment. As our data show, finding a common place increases the chance of receiving a message by about 40%, which is a lot. We also use geolocation in anti-spam.
Kozya: First of all, we make it difficult for our users to triangulate other users. Next, using geolocation, we can determine that users have dramatically changed their location, and there may be two cases. Either the anti-spam worked, the user decided to move to another country, and bother other users, or the user had a hijacked account to hackers from another country. We take action in such cases.
In addition, for the intersection service, we developed the so-called "Taxi driver mode". People who constantly move around the city with the included navigator generate a lot of accurate geodata. It is clear that they will have a lot of intersections. So that these users do not become familiar and bother other users, their intersections are generated by special algorithms with more severe filtering.
We talked about how good is geolocation, where we use it, let's talk about another problem, namely the problem of collecting geodata.
Geodata collection
This is a timeline, and from the moment your application starts up to the time it gets geolocation with a given accuracy, time may pass. In order to get geolocation faster, you will have to additionally use sensors that are not economical in terms of battery - barometer, gyroscope, etc. But even with the use of all possible sensors that are on the device, there is no guarantee for obtaining the accuracy of the specified coordinates.
Let's read the definition of accuracy directly in the Google documentation: "Accuracy is the radius around the point within which the user is with 68% probability."
Or, more simply, with a probability of 68%, we are right now somewhere here.
And we can not be. As you can see, two points have come, and the distance between them is much less than the accuracy that they give out. With such geodata also need to be able to work.
Obtaining accurate geodata depends on the time, they may not come at all, you need to be able to handle it. Let's talk how to test the assembly and sending of locations, without leaving the office, at the earliest stages: when you need to check that your system in general is able to at least somehow take geolocation.
To do this, it is wise to use the simplest available tools, for example, the Android emulator. In the emulation mode, the location contains the simplest things, such as the emulation of the location itself, and the loading of the GPX route, which Sasha will tell about later.
Curiously, the default location of the Android emulator is Dalvik village in Iceland. Dalvik is a virtual machine in Android up to version 5.0.
On the other hand, on iOS for some reason, I myself do not understand why, the simulator is much richer.
Host: Yes indeed. Apple is usually very user friendly, but engineers have a huge popabol. However, in this case, Apple thought about us, and we have as many as 3 options available: jogging, cycling and driving around the track.
This is convenient because the system returns us all the necessary data about the coordinate itself, speed, motion vector, horizontal and vertical speed, and in some cases even the floor. Very convenient for testing geolocation, without leaving the office.
But sometimes, if you roll the application into the background, the system will not send you coordinates at all. This is either a Xcode bug, or a simulator, or macOS itself. To defeat this, you will need to either kill Xcode, or a simulator, and if none of this helped, then reboot. But if you started the simulator and everything worked for you, and then after some manipulations it stopped, most likely it’s still a bug in your application.
The next thing we use is our favorite Xcode development environment. We connect with a debugger either to the simulator or to a real device (this is important, few people know that on a real iOS device you can simulate geolocation), click on the blue arrow, or in the menu choose Debug> Simulate locations, and see a drop-down list with dots, which Apple added - Moscow, London, etc. But we are interested in the “Add GPX File to Workplace” button at the very bottom, which allows you to add a GPX route.
To generate it, I recommend using Maps to GPX converter . At the entrance, he accepts the route from Google Maps - both the full URL and the shortened one. The output generates a GPX file for you: in fact, it’s just a subset of XML with time and a point in space, then the system interpolates the whole thing. This GPX file is compatible with Android, iOS and Windows Phone, GPS trackers, etc.
In fact, this tool was created in the days of the Pokemon Go boom, thanks to them for that, testing made it so easy. The only thing is that if we generate a GPX file with this tool, the system will not determine the speed of movement on iOS, so if you need to know the speed, it is better to use the simulator.
Let's talk now about the green bucket.
Kozya: Since we noticed that the emulator is not as rich as the iOS simulator, we took advantage of the fact that we can install any application without restrictions.
The first application that I recommend to use is Lockito , which is very convenient, in fact replaces the simulation of the tracks Apple has with you. The point is: you start the application, specify points in space, the type of movement between these points (be it in a straight line or some type of transport) and the parameters for issuing coordinates, speeds, etc. Run the simulation, and then just look in your application as you seem to be moving in space.
The second application is GPS Status & Toolbox . What is convenient: you can run it in multi-window mode, and see how your application looks on small devices directly on your large device. Well, show what the geodata system of your device gives, what your application receives, and compare it. If you fall into some kind of anomalous zone, when your location does not correspond to a real location (for example, you were suddenly transferred to Vnukovo), you can use the GPS Test to understand why this happened.
Keep in mind that when using Lockito, you should be able to use Location Mock, if your application uses libraries that solve for you the problem of using any geodata sources that I talked about later. And if all of your geodata sources are turned on by default in Android, you will often be transferred back to the point where you are at the moment. What is the reason: any application that emulates a location, emulates only a GPS subsystem, so you need to switch data sources such as GPS data in the settings, and everything will be fine.
Let's briefly summarize: we realized that Maps to GPX Converter is very good, you can download a GPX file onto different devices at the same time, and see how different operating systems handle the same routes. Well, out of the box iOS, unfortunately, is richer than Android, but Android is green, beautiful and generally better!
Now we understand that our system accepts data. Now we need to understand that something somehow works, that is, to start testing business logic.
Business Logic Testing
To begin with, we were faced with the fact that our business logic was too big, and we could not keep everything in our head. What was the problem: we had a large number of files, features and classes responsible for a particular system of processing locations. In order to reduce the geodata processing intervals or the distance between receiving coordinates, it was necessary to search for it all, change, build the application, and we could miss something, because you won’t keep everything in your head.
For this we have created a convenient configuration file. Here is an example of a configuration file on iOS, where you can simply change all the necessary data, build your application with your favorite Xcode and start using it.
Host: The next problem we have encountered is information noise, because without evidence of the existence of bugs (for example, screenshots and detailed logs), the developer can often not even understand in which direction to start digging. When testing geolocation, this is aggravated by the fact that there are a lot of variables in the equation. It’s not that difficult to reproduce the bug, sometimes it’s not possible to get the same set of coordinates twice with a given accuracy there. Therefore, without logging, testing can create more information noise than real benefits, you will simply distract your developers.
Also, let's be realistic, often developers add logs for themselves. But even if they add logs for testing, they often do not fully understand what we need. Therefore, in our case, we only saw the coordinates that were sent to the server. We talked with the team and decided what we need from good logs, let's talk to you about this too.
First you need to understand in which mode the coordinate was registered, This can be either a background when the application is in the background or killed, or the foreground when you see the application UI.
Next we need to understand how it was received: directly from GPS, or from some other providers, which we will talk about a little later, or the system could itself push us the coordinates if we use this or that API (say, geofencing, visits API or significant location change API on iOS).
Then you need to log everything that can be done about the coordinate: accuracy, altitude, speed, motion vector, acquisition time up to milliseconds. This is also very important, often the coordinates measure their accuracy in steps with a difference of several milliseconds. And any other information that will make your life easier: for example, how the user moved (jumped, ran, rode a bicycle, floated on a boat), Wi-Fi is turned on or off, etc.
And finally, we need to understand the principle on which we will send all these coordinates.
If you have simple business logic, then it will be just a timer, say, every 30 minutes. Otherwise, it may be some other conditions: either the business logic you described, or the application was killed and then revived. It can be killed out of memory killer, you could kill it yourself, or it could just be painted over. It can be revived by push notification or some kind of API. Since you died and revived, please register and send the coordinate to the server.
Ok, we collected these coordinates and sent it to the server, but for some reason we did not get the expected result: either we didn’t intersect, or we don’t register somewhere. We go with our feet to our developers, ask what is wrong. Client developers say, we don’t know, let's go to the server developers. We go to them, they meditate on the PHP-code, locate or in the database, they said what the problem is. In general, we went to them a couple of times and very quickly tired them out, so they made us a very convenient web page based on the logs collected, where we see all our movements superimposed on the Google map:
It is convenient to consider coordinates with an increased level of zoom on a large monitor, instead of doing it on a device. This helped us to find explanations for all strange situations occurring in real life, when we thought “we are here,” the system determined that we were in a different place. Sometimes we do it ourselves for some error, and sometimes we find bugs on the server in this way, when he wrongly filtered out certain coordinates. In this tool, it is convenient that the marks on the map are coded with colors, and they show why this or that location is invalid (it was too often registered / sent, its accuracy is low, or something is wrong with it). In general, logs are power, I recommend.
Kozya: We realized that with good logs you can prove that this is a real bug, not a feature, or it is reproduced, and take the developer for ... c red-handed :) Let's talk how to save 7 kg of nerve cells. Sasha and I love to save nerve cells, which is why it is so big and beautiful, which of us is big, and who is beautiful - you decide.
It was the debug menu that saved us an additional seven kilograms of nerve cells. On the Android menu is simple. And if suddenly you need more detailed information, you can install the GNSSLogger toolfrom Google and get even more additional information about how the satellite navigation system works, up to the values of atmospheric interference at a given point in space. I do not know why you may need it in most cases, we do not need it, so we made the simplest menu. You can see everything about the current location, see the map of movements, how you moved. Very handy tool on Saturday morning to understand what you were doing on Friday night! There is also a logging system where logs are recorded, well, and some additional tools: for example, it is very convenient to switch the geolocation system from fake to real, send logs to a computer for further study.
On iOS, the menu is more fun, but it's iOS.
Host: We have it a little more complicated, and we did it in one go, unlike Android, where we did iterations. Because we immediately knew that everything is bad on iOS, and we need all this information! The very first switch that we are especially proud of is local notifications about the location manager.
That is, you can minimize the application, kill, lock the device, but as soon as something changes, you will receive a notification. Not that you don’t need to enter the debug menu and watch the logs, and even the application doesn’t need to be launched: the device automatically turns on the screen when you receive a notification, it is very convenient. Just below we have two sets of coordinates: this is the last known location, and the last one sent, also for our convenience.
And also there is a view with Apple-maps, on which we build our tracks, for the same reason as Kohl explained: we connect two points and see if we were there. It has an interesting pin that shows the time period. To see it, you need to use the Visits API, which is available from iOS 8, that is, for a long time. From the point of view of the system, this works quite cleverly, because the system determines for us whether we have entered a point or left. We went somewhere, and after about five minutes of being there, the system understands: “Yeah, we probably went somewhere,” sends a notification to our application that at such and such time you went to a point with such coordinates. After we left, she also sends about the same exit notification in about five minutes. Accordingly, we know that we spent there, let's say45 minutes. For the functionality of the “Intersections”, it’s just great: you sit and drink coffee, a huge number of people pass by you, and you intersect with them. Just a great API, it is a pity that it did not appear from the very first version of our service. We did it under iOS 7.
All of our coordinates, which we record, are coded with colors so that you can quickly run through your eyes and understand how it was registered: the coordinates in the foreground are white, the background is gray, the visit is purple.
The mobile tester is therefore mobile because we carry everything with us. In most cases, this debug-menu was enough for us, but the main problem of mobile devices is the presence of a battery.
Energy efficiency
Kozya: And the more energy-efficient your application, the farther from the outlet you can move. Let me remind you, it was 2014, there was little information about how to test power consumption, and how to correctly test geolocation services.
Let's talk about the general methods that we found first. For a start, we used the Power Meter. This is the simplest device: on the one hand it connects to the power source, on the other hand the data cable is connected, your device is connected to it, and it shows the current. But what kind of current it shows is a problem.
There are two cases. First: if your battery is not charged, it shows the charge current that your phone consumes in order to charge your battery. This is not quite representative data.
And if your phone is still charged, then again you do not see the real current (with the exception of Android, I'll tell you later). Because the phones are configured in such a way that if there is an external source of energy, they also perform synchronization, application updates, and in the latest version of Android they also compile the code for you. Also unrepresentative. On android, you can turn off external power by software, then the Power Meter will probably show the correct data. On iOS, this is not possible.
There is also a special “Yandex method”, about which here, at Heisenbug, there is also a reportfrom the guys from Yandex. But, unfortunately, this method did not suit us, because we do not measure the power consumption after each commit, but move in different modes. Guys, I'm sorry, it's really inconvenient to walk outside with a device that has a back cover ripped apart, and a box with an Arduino connected to a laptop is connected. On the street, at least, they won't understand me!
Let's talk about the measurement methods directly on the device. First of all, let's talk about Android, because it's the letter A.
The very first thing you can do on Android is to go into the power settings, and see what's going on. If you are terribly unlucky, then you will see your application in the list in one of the first places. Although, of course, if you constantly use your application, it will appear in the top anyway, simply because you use it so much.
Going into the advanced power consumption information on the latest versions of Android, you can see a lot of useful information: using the CPU in the foreground, in the background, using sensors (for example, GPS), etc.
Why is there additional Google Play Services? The same application on different versions of Android will have different power consumption: prior to Android 8.0, your application, when using Google Play Services, caused the power consumption of these “services”, and not your power consumption. By the eighth version of Google, I realized that users complained too much about the “battery-burning Google Play Services” and said: “Ok, now any power consumption that was caused by your application goes back to you”. And you see your real power consumption, so put an eight and be horrified or delighted.
The next method we started using is Test Fairy, a sandbox library embedded in your application and recording a large amount of data. We use it in the case of beta users, they get all sorts of buns for it, like free credits, and we get a lot of data from them.
Some of this data is energy consumption, but not everything is smooth here either. The user session is basically 1-2 minutes, then it closes, a new one begins, and the battery change over this period is not so interesting, it can even be zero (the scale there is not in mAh, but in percent, and on modern devices with batteries 3000+ mAh one percent is quite large). Or the user may have a long session, like this user with a 22-minute session, but his phone was connected to an energy source, so we did not see anything. The rest of the users, who really have a discharge, are so few that the data simply cannot be interpreted intelligently.
The next tool I started using immediately, as soon as it came out, is Battery Historian. Thanks to Google, a unique tool, is actually a “fingerprint” to determine who and when the battery was consumed. Even if you do not research your application, you can see which other applications and why you ate the battery.
Here you see that I chose a moment in time by clicking on the graph, I see that our application was active for 3 minutes. I see which sensors have been used, which services, and this especially helps with energy research: it allows you to understand whether the application is eating geolocation. It happens that developer accidentally created an infinite loop and forgot to make a way out of it. Anything can happen.
In order to additionally hide behind the rear, we use monitoring. We have a very strong monitoring team, and in addition to all the metrics, at our request, they also monitor the power consumption of our users, and after the release we can see the trend and react to it promptly.
The system works very simply, we send the battery charge events twice: once when the application starts, and the second time when the application is minimized or killed. We build trends on the basis of this, very convenient, very useful, and we are well covered. And on iOS, all the pain.
Host: As usual, everything on iOS is cool for users (it's not so easy to recharge a battery, like on earlier versions of Android), but for engineers it's a great sadness.
We started with the very first tool, the same thing: “Settings” - “Battery”. The tool as a whole is very bad, it has only one plus: it shows how much your application works in the background. For us, this is important because we collect and send geolocation, including in the background.
And then the pain and suffering begin. The tool is very inertial, updated about once per hour. Therefore, if your application is working normally for 5 minutes, and 55 is eating a battery, if not in itself, you do not see it. And if you want to pre-install two devices, put two different builds on them and compare them for power consumption, not only will you see the first result in an hour, so if you don’t run three or more applications, you won’t see anything and postpone again all for an hour.
The next tool is the Energy impact scale in Xcode. You connect the debugger to your application, press the third cell on top and see the scale that changes in real time: from the green zone, where you do not consume energy, to the red zone, where you eat, if not to yourself.
A little below shows why it is being consumed: say, the CPU is 100% loaded, or you do not let the system fall asleep, or awake it all the time, or forget to turn off the GPS after it is not needed. But without a developer, it’s quite difficult to figure it out: for example, because when you start you will eat CPU, because you need to start the application and download the data, you will have GPS turned on to send the location to the server and get people near you, and you will also drop cache to disk. Normally or abnormally, the devil knows. Therefore, we have developed a set of cases and run them with the developers after each big refactoring.
The next tool is the power settings in your iPhone: go to “Settings - Developer - Instruments”, turn on the record of power consumption and work with the network. Working with the network again came in handy for us, because we send these coordinates to the server.
But the tool, again, is not very, because it writes data about the entire system, it is also difficult to compare something between applications - their car is on the list. Energy consumption data is shown in some incomprehensible at first glance fractions, and not milliampere-hours, like on Android. Fractions, oddly enough, show how much the device will live with the current power consumption. For example, 1/17 means that in a given time slice, with the current power consumption, the device will discharge to zero in 17 hours.
In order to write data specifically for your application, you need to connect instruments exactly to your application. If you walk along the street with a laptop, cord and device, you may not understand.
This is the sadness of iOS, I hope, in the report of the guys from Yandex, there will be something great that will help with this. But the guys on Android are cool - Battery Historian, charts, guys are covered from all sides.
Our optimizations and energy solutions
Host: We talked about how to measure energy consumption, now let's talk about how to make certain decisions for optimization. Fortunately, our developers are cool and read the documentation, but if something is missed somewhere, the testing team comes to the rescue. In most cases, we tested this or that theory, and it was either confirmed or refuted. We open the Location Manager documentation in iOS and see that first of all Apple recommends that you reduce the accuracy setting when determining the location, and we reduced it to 100 meters.
In any case, the system will try to give you the coordinates as accurately as possible. At a minimum, because you most likely have another application on your device that uses geolocation. That is, you can get it "at someone else's expense": if another application received a location, you can use it. For example, five minutes ago, another application received geolocation, in principle, sometimes it is enough. Relaxing the settings allows Apple to save on power consumption.
But, as usual, it is difficult to be immediately smart and beautiful, and not only on iOS, but also on Android. For example, you were in the parking lot for a long time, or you traveled by train at high speed, you had low accuracy. You start the application, and you have two ways to get coordinates: either quickly, but not exact coordinates (up to 1000 meters), or long and accurately. But, as Kolya said earlier, “long and accurately” does not guarantee its receipt at all, if you are in the basement, you can wait 15 minutes and not get (you, for example, in the basement). Therefore, we chose the path “quickly, but not exactly,” and developed a mechanism for studying the coordinates.
This answers the question why we needed a selfie stick during testing. We take the device, laptop, lanyard, connect to the debugger, go down to the parking lot, trap the device, wait two minutes for the system to fall asleep completely. Then we go into the elevator, go up to the fourth floor, quickly run to the window, unlock the device on the way, set up the device on the selfie stick behind the window and see how the system specifies the location in one or several steps. This, of course, is fun and interesting, fortunately, it was covered with unit-tests, and not a single phone was damaged.
In general, the refinement mechanism works simply: for 20 seconds (after launching the application or after we brought it out of the background) we listen to the coordinates from the system with increasing accuracy. 20 seconds is a timeout chosen empirically after experiments on basements and parking lots :) After 20 seconds we send more accurate coordinates, if they exist, and if not, then we slowly die and that's it.
Then we decided to use the Significant location change API. Instead of waking up the application and turning on the GPS (which is very uneconomical), you subscribe to the API, and the system itself pushes notifications to you about a significant change in coordinates, you just need to save them to the database and send. Very cool.
What exactly means "significant", "significant"? This is an unknown quantity, it depends on the speed of movement, mode of movement, energy consumption, mode of energy conservation, a lot of unknowns. In general, when walking on foot it is 750 meters, when driving at a low speed it is from 750 meters to several kilometers. In terms of power consumption, this costs you practically nothing, you just need to write down the coordinates or send them immediately. But, as usual, Apple is bad again.
We can not make a service that works only with coordinates and pumps data into the application, like on Android. So, if we are nailed and then revived, then we need to revive the entire application. To eat a battery a little bit, and not very hard, we have to initialize only parts of our application. That is, we initialize the system of working with the server and the system for working with the location: we do not load encounters (our first and main screen), do not initialize any screens, and so on. Otherwise it would be a misfortune.
We also use the Visits API. I have already talked about it before, but our first version worked with the iOS 7 API, so initially it was not there.
Also, while collecting and sending coordinates and performing all sorts of tasks, Apple recommends that you relax time, plus or minus a few seconds, for the system to form a wad of tasks, wake up, complete the entire wad of tasks and fall back to sleep. Otherwise, she will wake up under each puzzle and eat you a battery.
And finally: we strangled a little timeout when working with the network. By default, iOS is 120 seconds, as is the NSurlsession runtime in the background, which we use when sending coordinates to the server. This is a lot, we have strangled it, if my memory serves me, up to 30 seconds. That is, if we have a bad network, we slightly hammered the server and did not receive an answer, then we died and rescheduled the dispatch, say, for 5 minutes to the future. If this is done for 120 seconds, we, again, begin to eat away the battery. Especially if you do not have Wi-Fi, but have 3G: working with a cellular network is less energy efficient
Let's talk about Android now.
Kozya: On Android, we immediately started using it after the appearance of the Fused Location Provider. It is characterized by low power consumption, because the library itself decides for you which source of geodata to choose. GPS is not always the best and fastest way to find your location.
The second advantage is the possibility of obtaining geolocation at someone else's expense. As Sasha said, they cannot create a service on iOS, but we can create a service on Android. What we did, and just get the location for someone else’s account by subscribing: if some other application needs a location, for example, Yandex.Navigator, we will get this location for ourselves, just save it to the database and then send it, and all power consumption will go to the navigator .
You can also set the desired accuracy so that your service does not receive a large number of coordinates. Because, as we checked yesterday in the Moscow metro, the accuracy can be up to five kilometers. You can set the desired accuracy of obtaining, for example, "we need coordinates with an accuracy of 100 meters and more precisely," and the rest will be filtered by the system, very convenient. There are also different strategies: getting by timer, getting in case of launching some service, the user has entered some place. There are many strategies, so read the documentation and find the one that suits you best.
Here I would stop talking about our optimizations, if there is a problem there, that the Fused Location Provider covers only 90% of our needs. And another 9% closes Legacy Location Provider - this is an old provider that has been in Android since ancient times. You can use it, but it is not as energy efficient and is needed for old devices that do not support new types of Google Play Services, or for devices without Google Play Services, for example, from an unknown Chinese company Xiaomi.
The remaining percentage of data is closed by a self-written system called Aggressive Location Provider. It is based on the Legacy Location Provider, and is needed in at least two cases:
Firstly, it happens that the Fused Location Provider did not return coordinates that satisfied us (for example, your application is the only application in the system that processes geodata, and you decided to subscribe for someone else’s account and received nothing). And our product managers wanted from us a large number of coordinates, and we were so reinsured.
The second case. Google Play Services is an application that is written by people, so that it can also "die", it may not properly restart after the update, and many other things can happen, so an additional safety net is always important.
At the same time, Aggressive Location Provider is very reverent about the user's battery charge. For example, in the event of a charge drop below 20%, switching the phone to flight mode or manually turning on power saving mode, we stop using Aggressive Location Provider and generally touch the phone in this regard. To respect the user and his settings.
In addition, there is an Activity Recognition API as part of Google Play Services - a convenient system of user activity patterns. There are 4 basic patterns: walking, running, biking, and being in transport (be it public or private).
In addition, there are additional patterns, for example, a very comfortable still. For example, you took your device, went to a bar, put the device on the table to communicate with other people, and your phone is still. The pattern still worked, we received this information and we remember the location not far from the moment when we got still, or we are just trying to clarify the location now. After that, we forget about the issue of the location of the device until the user did not pick up the phone to exit the bar, because he had already talked. And we will understand that from such and such for such a time the user was immobile at this point.
Everything is fine here, except in some cases: for example, you go by train St. Petersburg-Moscow, put the phone on the shelf, the train has an ideal suspension, the railway is direct, your phone is still. You are coming to Moscow, want to see if you crossed up with that girl in Vyshny Volochok or not, but unfortunately you will not cross, because we got still, and you may have thought all the time that you were at the Moscow railway station St. Petersburg. Therefore, you still need to reinsure yourself and listen to the system: if the location does change, then disabling the pattern, because the pattern is only a probability.
So, you run in everything that you have in your laboratory environment, you realize that it somehow works, but still it is a spherical horse in a vacuum, because in real conditions there may be certain situations, you need to start to understand them . For this you have to go "in the field."
Exit "in the field"
Kozya: And in order to go out into the field, you need to understand what to take with you. You need to take real devices, with different OS versions, Wi-Fi turned on / off, with different power saving settings, with and without SIM cards. I want to note that two different SIM cards may have different power consumption: for example, some support 4G, while others do not. It happens that even two SIM cards that support the same frequencies have different power consumption, because they have different firmware. Sasha and I encountered this using Vodafone SIM cards from different lots.
Next you need to understand your user. Because to find user bugs, you need to be, as a user, you need to move, as a user, do the things that the user does. Well, to be a user of your application, in the end, dogfooding has not been canceled. And that's what we did.
Host: First of all, we decided to leave the office and take a walk around the neighborhood. Why is it so convenient? Yes, the fact that the positioning accuracy is very strong due to the different density of development, different density of Wi-Fi networks and cellular networks. London is very uneven.
Also, the “ragged” pace of walking allows you to check the send intervals. You do not walk at the same speed: someone blunted in front of you, you overtook someone, stood at a pedestrian crossing, descended into an underground passage, and so on. Specifically, in our case, it even allowed us to find a bug. If during the formation of a bundle of coordinates, before sending, they received coordinates, they were added both to the bundle to be sent and to the cache. Accordingly, in rare cases, we have duplicated these coordinates. Reproduced, to be honest, by chance, but the case is interesting.
It is also very convenient to test "visits" on iOS. Let me remind you that the distance between the two points of the signification change is 750 meters, and the “visits” are sent with a delay after plus or minus 5 minutes. Why it is convenient: the distance between the pubs in central London is much less than these 750 meters.
Therefore, you go to the pub, drink a pinto, go out, in 5 minutes you go to the next pub, and something wrong may happen here. Specifically, in the case of iOS, we chewed either the exit from the previous establishment, or the entrance to the next one, if they were very close in time. It helped us to rewrite this whole thing on Swift, because the static analyzer works much better there and helped us determine that we used the wrong constant and the expression is always false.
In general, it is easy and pleasant to test: drink a pinch (usually I drank a pinch with a goat), intersect, get a push, open it, look. If the place is correct, and / or we have already been tested, you have to go home.
Also, walking around all sorts of institutions allowed us to find a potential bug that could ruin our entire system of Chekin training. In London, in addition to pubs, a lot of all kinds of institutions per square meter. Let's just say, on the area of 100-200 square meters there can be 4-5 cafes. And the accuracy is usually 10-30 meters. Therefore, to determine that you are in a particular cafe is very difficult. And we act rather nontrivially: we go to the cafe, receive an entry event, pick up the connected Wi-Fi point and its MAC address (if, of course, it is), and send it to the server. That is, if users constantly come to this point, they have the same Wi-Fi, then with a high degree of probability you are still in this place.
But as it turned out, in London there are still open Wi-Fi networks, and in three minutes I can walk to the next establishment and already be in it, and again grab the access point and send it to the server. Moreover, the server was stunned by the fact that it has two different Wi-Fi networks for the entry and exit events, but also physically the distance between them can be 300-400 meters. Depending on how fast you go, this must be taken into account, so by a strong-willed decision we turned off the recording of the access point name to the exit event.
Then we decided to go by public transport. First of all - by buses, because the center of London is very crowded, and buses go at a low average speed. It also allowed to check and ottyunit definition of the nature of the movement: you are driving, walking, etc. Such a definition is a probability, that is, when riding a bus, conditionally, with a probability of 90%, you will be determined by riding a bus, and with a probability of 10%, say, by bicycle. In some cases, you will need to adjust the corresponding weight.
Also when riding the bus, we caught a funny server bug. When stopping at a pedestrian crossing or at a traffic light, we sometimes got a location. Since the server did not know through what we get the next location and what we had previously braked, I tried to check us in the nearest establishment to the bus stop. We decided this problem is simple: we added the definition of speed (in meters per second), and if the speed is not zero, then we should not check us at this establishment.
Then we decided to go down to the London Underground. It is very old, there is no cellular network there, it does not catch GPS, therefore the least cheat way to determine location is via Wi-Fi: go to the car, reach the next station, Wi-Fi is automatically connected, the location is also very cool and convenient .
Then we decided to drive a car and a taxi. What is convenient: the operating system is trying to tyunit power consumption, if you are moving at high speed, and your navigator is not turned on. Therefore, when driving at a speed of 20-30 km / h, this is 750 meters in the background, and when driving 110 km / h, it is already 2-4 km, and if you are traveling by high-speed train to the airport (in London we drive about 250 km / h), and you do not have many cell towers, it is already 4-11 km depending on the density of towers, because fast-moving GPS objects are difficult to fix, and there is a lot of metal in the train, which does not contribute to location accuracy.
Also, depending on the speed of movement, if you are using the Geofencing API, you must correctly set the radius. Geofencing works quite simply: you go to a point, put a radius around you, do something at the exit from it (say, send a packet of coordinates). Or, on the contrary, you go to a certain place. Suppose you go to McDonalds, they identify you and send a push “Today, a burger for you is two times cheaper.” If you move quickly, then you need to put a larger radius. Otherwise, you will land the battery, will often go out of this radius, or, on the contrary, you will not leave it if the accuracy of the coordinates exceeds it.
Kozya: In addition, in Android 7+ there may be another joke. You have a phone, you get in the car, put it on the passenger seat, drive from point A to point B. You have arrived, want to see how many locations your phone has received, look, but they are not there at all. What is the reason? Google decided to make users good, and developers bad, and introduced the so-called doze, sleep mode. Not only that when the phone is not in use, it is “asleep”, but also Google added an aggressive doze from the Android 7.1 version. What it is bad for is that your phone begins to analyze the situation faster, to understand that it is not in demand, just in the case when you threw it on the passenger seat and drive to point B, and as a result does not receive coordinates. After reading the documentation, we found that you can get the coordinates at least four times an hour - from a black sheep, even though a shred of wool.
We realized that our horse is no longer spherical, but real. Let's talk now about the worst.
The reverse side of the field outputs
Kozya: The first scary thing is that the devices can break and fall, so stock up with good covers before any field exit.
And the second is regression.
Host: After we checked the bugfixes, the main functionality, the first thing we ask is: didn’t we slacken by the number of coordinates collected and sent out? Kep hints that you need to take two devices, put on them various assemblies and walk with them, compare the coordinates. But no matter how. Kolya used to talk about SIM cards with different power consumption, and we were faced with another interesting way to prove that devices are very difficult to put in the same conditions.
I had one test device in my right pocket, and the other in my backpack, because it’s dangerous to put in my back pocket, they can pull it out. As it turned out, when walking the device, which was in your pocket, moves more, wakes up more and collects more coordinates. When I came to work, I saw that the device that was in the backpack collected one and a half times less, and various application builds had no relation to this. Therefore, try to put the device in the most similar conditions.
We also recommend you a long-term service check in the background, because in modern devices there is a disgustingly large amount of RAM. For example, there are modifications OnePlus 5 to 6 and 8 GB of RAM, in which case your application will live in the background for a very long time, and if it lives, then let it work correctly. We usually leave the application connected to the debugger and in motion simulation mode at night or on weekends.
But Kohl helped us with the toughest testing when, during the release of this functionality, he had to drive a car from Moscow to London. We gave him several boxes of test devices, he collected us a huge amount of coordinates in two days and 3000 kilometers, crossed with users who had the feature turned off (including himself), collected gigabytes of logs for us, helped us to find several bugs, who corrected before launch.
Let's talk now about bugs, after all we have a testing conference.
Kozya: After the release of features, we began to receive coordinates from the past and from the future. What caused the problem: our users move and can cross time zones, go into the past and the future regarding the timestamp in which the original coordinates were obtained.
In addition to the bugs of devices and firmware in determining the timestamp when crossing time zones, similar errors are caused by other bugs, but this can be solved simply. A device always has time that is greater than zero - this is uptime, the time since launch. We add it when we receive coordinates, and only then, when we need to send this packet of coordinates to the server, we send it with uptime time. In principle, this closes most problems.
The second problem is people who are beginning to teleport. In addition to the things I mentioned earlier (the user abruptly changes the coordinates to bother other users, or hijacked an account), the very real user also begins to teleport in space. What is the reason: in the first place, with the fact that when the coordinates are refined, the point can walk. Refinement of coordinates and center shift can occur at a very high speed. And we just limited the maximum possible speed of movement of our users to the speed of a passenger liner, more so far it is unrealistic. This resolved 99.9% of problems, with some interesting exceptions.
Host: Let me remind you: if you do not catch or GPS is turned off, the location is taken from the included Wi-Fi or base station. We encountered in nature with at least two error cases. The first was when Badoo was celebrating 10 years in a beautiful country house with very thick walls and a ceiling, respectively, we didn’t catch GPS. Our valiant administrators attached access points from the London office, and when launching the map applications and our application it turned out that we were in the London office. Fortunately, modern access points can update their locations fairly quickly, from a few minutes to a few days. We have the whole thing fixed in a couple of hours.
And those who live in Moscow know a more popular story: if you approach the Kremlin, then you can be “teleported” to Vnukovo, and this also happened to us. Googling, we found that we replace the GPS / GLONASS coordinates and set the Cell ID coordinates in Vnukovo. The guys from Yandex.Taxi even had to make a hack to more or less normally bring or take people from there.
Also, some users teleport to China and Brazil. As it turned out, teleported mainly to Blackberry devices to Brazil: it turns out that when they had something to do with the GPS work subsystem, they were teleported to the place where the device was assembled in Brazil. And Chinese were transferred to China, in which something went wrong.
Also, some devices on iOS were being transferred between two points. If memory serves, up to iOS 9.2 they had a very nasty bug: when getting a location in the background, the system with a difference of 10-15 milliseconds allowed for a very old location, say, received 6-8 hours ago. You go forward, then jump back, then go forward. For this we had to write outdated coordinates filtering: both on the client and crutches on the server, it’s not always possible to do this on the client. The server simply smoothes that whole thing.
The last bug that I personally drank a lot of blood: if you are simulating geolocation on a real device, and at this point Xcode popklohelo, or you pulled out the cord during the debug session, the device will freeze in the last known geolocation. The curiosity of the situation in my case was that, before going home, I simulated the exact coordinates of our office, took this device home, and then returned and was surprised to see that he did not receive the coordinates even once, in the end it was worth a few man-hours - mine and the developer.
We all told what we wanted, let's sum up.
Conclusion
Kozya: The very first thing we realized: without a good toolkit, be it an IDE, logs, or additional applications, testing geolocation services will create more information noise than real benefits.
The need for field outputs when testing geoservices is obvious, but the problem is that even going out to the field, you will not find all the bugs. We have described only some of the pitfalls, you may have a lot more, or not at all, depending on how you do it.
All bugs found by you, it is desirable to classify and somehow mark. These can be bugs of your functionality, API bugs, the device itself, or geolocation, as is the case with the transfer to Vnukovo. These bugs need to be borne in mind so that if they are found, we should immediately speak quickly: this is a geolocation class bug, and we will not fix it, because it does not make sense.
Testers are the link between the user and the business. It is clear that the business from us wants to have a lot of coordinates, and users do not like it when their battery drastically sits down. Because of this, you need to think about measuring energy consumption as early as possible. But it is also important not to re-optimize at very early stages of development, because then it will be more difficult to test and develop.
And the most important conclusion that we can make today at this conference: the density of pubs in the CIS is much less than the density of pubs in London, and if you suddenly needed to accurately test your geolocation services, take a walk through the sights, come to us, we will gladly will help. Thank!
Minute advertising.If you liked this report from the Heisenbug conference - note that the new Heisenbug (May 17-18, St. Petersburg) is already coming up, there are also many interesting things in its program, and you can already study it carefully . We hope to see many of you there!