I had a task to build library which could be used for p2p data exchange in situations where there were no data-networks available. Also the data exchange should if possible be handled automatically as soon as device which is implementing the service is found to be nearby, this all should also happen without any need for user interaction. The implementation should also work with normal devices, with firmware versions generally available and without rooting the devices.
In the beginning of the study three different technologies that could be used with android devices for the use case were identified to be:
- Bluetooth Low Energy (BLE)
- Wi-Fi Direct
I have been writing about the Wi-Fi Direct parts, and will be writing more until I get the task finished with it. And with this article I’m concentrating on the Bluetooth parts.
The BLE then offers advertising the service and locating it without any need for pairing the devices. Unfortunately with android device, the peripheral mode required for handling the service advertising is only available with Android Lollipop versions, and only if the device hardware also support this feature. With currently available devices, the support is not really wide, thus this technology was deemed not to be feasible at this point of time, though I’m planning to get some work done with it later on.
The standard Bluetooth technically then has a two phase life cycle. In the first phase one pairs two devices together. In the second phase one discovers when a paired device is nearby. The pairing requires users of both devices to be close proximity and both device users to accept the paring, and thus it requires user interaction.
By default in Android when switching a device into discovery phase one has to get approval from the user and then a countdown begins during which time the device will make itself discoverable to other Bluetooth devices. This means that also the discovery phase cannot be fully automated, and when enabled it would only work for limited time period.
Because of the limitations listed for the standard Bluetooth, the implementation used in the case study is utilizing Android specific implementation of insecure Bluetooth sockets. This approach has one major advantage when compared to standard Bluetooth, which is that it does not require any device pairing in any stage of the data exchange. Which means that if we know the target device Bluetooth address, and the target device is listening for incoming Bluetooth connections, then we could implement the data exchange without user interaction.
As it was mentioned in the beginning the normal way on exchanging data is to first discover the peer, and then open data channel to exchange data. With this implementation the discovery and data channel establishment is handled in single step, and to be more precise the actual discovery step is omitted, and we simply opportunistically try to establish data channel between devices, and once we succeed with the data channel establishment, we then also have succeeded discovering that the peer is in our vicinity.
So in the beginning each device must have the list of Bluetooth addresses of the peers it wants to communicate with. The list can be delivered manually, by email etc. Or as with the example by discovering peers nearby by Wi-Fi-Direct peer discovery.
Then when the application is started each application must start listening for incoming connections. And once connection comes in, it saves the data into a database, so the device user can see them later on. And also it starts listening for more incoming connections, thus keeping the listening on for all times.
Then when the user schedules a message, it’s simply put into a database and marked as non-delivered. Then a scheduler is started, which will read the database items marked as non-delivered, put them in an array, and start looping through the array list.
In each loop the scheduler tries to establish connection to the Bluetooth address for the message, and if it fails, it then moves to next message in array list. If the connection establishment works, then the data for the peer is sent, and the item is marked as delivered in the database and removed from the array.
The scheduler continues the loop until it has delivered all of the messages marked as non-delivered.
There is a full example illustrating the approach available at: DrJukka/BtInsecureSync and the following video shows how you can use it.
The implementation itself is really simple, basically the challenges with the method was that originally there were no data on using the API in this way for extended periods. Thus to determine the feasibility of the API for any given purpose we needed to get ideas at least for following performance characteristics:
- how fast we can do the discovery
- How long much does battery does the discovery consume.
Both characteristics were measured using one test application, in which we had one address and we are continuously looping the search with it. Timing for each discovery round was measured, and to determine the battery usage, the test was run from full battery till the device battery run out. When doing the tests devices were not doing anything else, they did also not have any SIM cards and no other network activity, and thus in general during the tests, we can assume that the only part that consumes battery in the device, was the test application.
The test application can be downloaded from DrJukka/BTPollingTest. The test application was run on background with 4 test devices over a period of time, which after the values for minimum time, maximum time and average time spend on one polling round as well as the average battery charge drop percentage over an hour were measured. and the values are shown in the table below:
The N5 stands for Nexus 5 devices, and the N4 for Nexus 4, the 3 character number then indicates the firmware version (for example 501 is Lollipop 5.01). From the data we can conclude that one polling rounds takes about 5.2 seconds, thus we can in maximum get 11 rounds done in one minutes time, which in reality means that if we have 11 messages to deliver, we need to spend at least one minute of time near a target device, in order to be sure it will be discovered, and if we just have one, then we should be able to discover the device within 5 seconds from the time we come into the vicinity of it.
The run time is calculated from the battery usage data gotten with the tests, in it all devise were without SIM and without Wi-Fi, and without any other apps running, thus the power consumption should come only from the running the app and the HW it requires.
With the Nexus 5 test devices we are getting around 70 hours of run time for the app, with Nexus 4 it’s about half, with all devices the consumption would in general be in a level that the application battery usage should not be big issue when it is run in normal device with other apps running same time.
The sample implementations did show that the method indeed is usable, it can be used in situations where we need automated syncing with peers without any user interaction, provided that the following rules apply:
- We can get Bluetooth-Addresses of the peer devices stored in the device
- The number of peers to send messages is not high, i.e. less than 11 at any time (unless we can accept higher discovery time)