ukhsa-collaboration / COVID-19-app-iOS-BETA

Source code of the Beta of the NHS COVID-19 iOS app
https://covid19.nhs.uk/
MIT License
800 stars 179 forks source link

Discovery fails when both devices are locked #2

Closed lukeredpath closed 4 years ago

lukeredpath commented 4 years ago

Describe the bug I've been trying to see how the app works around the issue where an iOS app central cannot discover an iOS app peripheral on another device if they are both in the background (and/or the device is locked).

I did a lot of initial testing of this with an Apple sample project yesterday and could not find a way to make it work and am able to reproduce this problem with the COVID-19 app as well.

A few notes, I've had to make a few small mods to get the app running on my device to the point where it's actively scanning and broadcasting:

To Reproduce

  1. Install app on two iOS devices. In my test I'm using an iPad and an iPhone.
  2. Install the app on the iPhone, launch the app and make sure its working. Kill the app, turn on Airplane mode.
  3. Install the app on the iPad, launch the app, make sure its working (I'm running this one attached to the debugger so I can watch the log output). Background the app (verify using logs) and lock the device.
  4. Move out of range of the iPad with the iPhone, wake the iPhone up, disable Airplane mode, launch the app, close the app, lock the device.
  5. Move in to range of the iPad and observe no log output - the didDiscover delegate method is not being called on the iPad.
  6. Wake the iPad screen by pressing the home button - the didDiscover delegate is called and it springs to life.

Expected behaviour This was the behaviour I expected based on my previous testing however I was lead to believe that a way had been found around this limitation.

My understanding of the problem is thus:

Smartphone (please complete the following information): I'm using an iPhone XS and an iPad mini 4 running the latest version of iOS 13.

EDIT - some further detailed scenarios below.

lukeredpath commented 4 years ago

I appreciate my testing of this is limited at the moment and would be grateful if anyone else is able to reproduce. I've pushed the branch I was running with my small modifications to a fork which might make it easier for people to get up and running:

https://github.com/lukeredpath/COVID-19-app-Documentation-BETA/tree/mods-to-run-on-local-device

You might still need to copy the example GoogleService-Info.plist file to .secret/, update the team ID and configure provisioning.

benabrahamson commented 4 years ago

Hi - not sure how helpful this might be to your particular question, but this article goes into detail about the technical details and workarounds used in the app: https://reincubate.com/blog/staying-alive-covid-19-background-tracing/

lukeredpath commented 4 years ago

Sadly I don't think the above article really addresses the core issue. I've heard some suggestions that it might be relying on the Android app to wake iOS apps up but I'm not convinced that would work - even if an Android app connects to the iOS app (which is running in the background), it won't bring the app to the foreground, iOS will wake the app up in the background briefly (for about 10 seconds) and the device will of course remain locked.

Not ruling it out - I don't have an Android device to test this theory, but if this is the case then it seems like a pretty shonky workaround.

Before we speculate how they are working around this it would be good to establish if what I'm seeing is right, a known issue and that there isn't anything special going on in the app itself to bypass this issue.

jdmwood commented 4 years ago

I worked on a similar problem a couple of years ago and saw similar behaviour to what you're describing. Apple are very strict on restricting this kind of stuff so I'd be amazed if a trivial workaround could allow iOS devices to detect each other when locked. Having said all that, a practical test beats all else (so kudos to original poster). Someone else needs to repeat this test to add more data points.

itspolly commented 4 years ago

I believe they have a workaround which is feasible for use in the wild. We're writing it up now!

stephenheron commented 4 years ago

Some quite interesting stuff around how they might be getting around the background iOS restrictions can be found in the Android source.

Looking at the Apple documentation on background peripheral bluetooth, they state "All service UUIDs contained in the value of the CBAdvertisementDataServiceUUIDsKey advertisement key are placed in a special “overflow” area; they can be discovered only by an iOS device that is explicitly scanning for them"

I wonder if they have managed to reverse engineer this overflow area so it is accessible via Android?

Someone did some looking into this and it seems at least feasible: https://crownstone.rocks/2018/06/27/ios-advertisements-in-the-background

Will be very interesting to see if we can get some more details on how this operates from the developers.

jdmwood commented 4 years ago

It definitely appears to be the case that they're using Android to bypass this feature, but the key question remains: what happens if two iOS devices, both locked (inactive) encounter each other when there are no android devices in the vicinity

lukeredpath commented 4 years ago

Yes, based on that comment in the Android source and the Crownstone stuff which I was reading yesterday, it does seem like it is possible for Androids to detect the iOS app even if its in the background (although we're all aware of the risks in relying on reverse-engineering a private, undocumented implementation detail like this).

Whether or not an Android device connecting to a background iOS peripheral on a locked device is enough to make that device visible to other locked iOS devices is what I'm not convinced by, until somebody can demonstrate it working and explain how it's doing it. And if that is the workaround, as @jdmwood2 says, that isn't much help if there are no Android devices around - how many encounters will be missed in this scenario?

jdmwood commented 4 years ago

Just a thought having read a bunch of threads on Twitter about this. Anyone trying to reproduce this must absolutely account for a) new devices finding each other (the OPs point about peripheral state restoration and b) finding each other when both devices are locked before coming into range.

I think it would be very easy to get false positives if you're testing with devices which had already discovered each other (even in a previous test).

The gold standard is: can two locked iOS devices (as in, phone is in your pocket) find each other when they come into range for the for first time.

lukeredpath commented 4 years ago

I've continued to do some testing and I'll try and capture this on video tomorrow, but these are the scenarios I've tried. Interestingly it looks like there's more to this than the apps simply being in the background but it could also be related to the power state of the device.

In all scenarios I am starting with the following test conditions:

Scenario 1: App on Device 1 is in foreground, Device 2 app is in background

  1. Launch the app on the iPad from Xcode, observe it is I the foreground.
  2. Unlock my iPhone and turn off Airplane mode.

Result: iPad discovers the iPhone immediately.

Scenario 2: App on Device 1 is in background (screen on), Device 2 app is in background (screen on)

  1. Launch the app on the iPad from Xcode, press the home button and wait for log output to confirm app is in background mode.
  2. Unlock iPhone and turn off Airplane mode.

Result: iPad discovers the iPhone immediately.

 Scenario 3: App on Device 1 is in background (screen off), Device 2 app is in background (screen on)

  1. Launch the app on the iPad from Xcode, press the home button and wait for log output to confirm app is in background mode.
  2. Lock the iPad.
  3. Unlock iPhone and turn off Airplane mode.

Result: iPad does not discover iPhone (waited for up to 2 minutes keeping iPhone screen on throughout).

After waiting to see that the devices do not discover each other, discovery can be triggered immediately in one of two ways:

  1. Launching the app into the foreground on the iPhone (iPad still locked)
  2. Waking the iPad by pressing the home button to turn the screen on. This works with the iPhone both awake and locked.

In my earlier testing the above scenarios behaved the same if instead of using Airplane mode, I went out of range before launching the app on my iPhone and then came back into range. I'm using Airplane mode for convenience here so I don't have to walk up and down my driveway all night.

So it seems clear to me that the issue isn't solely related to the apps being in the background, but also to do with whether or not the screen is on. Some potential confounding variables that could be throwing off my tests:

lukeredpath commented 4 years ago

Would be great if somebody fancies reproducing my tests above with two iPhones.

stephenheron commented 4 years ago

I have had strange behaviour in the past with background behaviour while using Xcode to read logs.

I did discover that the app has a debug screen that allows you to see logs while not connected to Xcode. If you shake the device you will get a development menu with a number of useful options.

lukeredpath commented 4 years ago

Good spot - just tried scenario 3 untethered from Xcode - I put my iPhone back on Airplane mode again before unlocking the iPad, launching the app and using the debug screen to send the logs to my iMac. Log output confirms the same result.

It also sends over the contact events in plist format so I thought I'd take a look at that with a clean slate.

Deleting the app and re-installing on my iPad was also useful as it seemed to clear the cached state restoration data which means I was able to run the test with the state restoration code intact. I observed the same behaviour as before, here's a snippet of the log from the point I backgrounded the app:

23:40:04 info: Application AppDelegate.swift:183:applicationWillResignActive(_:) – Will Resign Active
23:40:05 info: Application AppDelegate.swift:194:applicationDidEnterBackground(_:) – Did Enter Background
2020-05-07 23:40:05.943201+0100 Sonar[784:192358] Can't end BackgroundTask: no background task exists with identifier 2 (0x2), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.

**** TURNED OFF AIRPORT MODE ON MY IPHONE HERE ****

23:40:18 error: Registration RegistratonService.swift:94:register() – Registration did not complete within 20.0 seconds
23:40:18 error: Registration RegistratonService.swift:177:fail(withError:reason:) – Registration failed: Sonar.(unknown context at $100eef8ac).RegistrationTimeoutError
23:40:18 info: BTLE BTLEBroadcaster.swift:217:peripheralManager(_:didReceiveRead:) – responding to read request with empty payload
2020-05-07 23:40:18.836045+0100 Sonar[784:192428] [AppCenter] WARNING: -[MSChannelUnitDefault enqueueItem:flags:]_block_invoke/141 Channel Analytics disabled in log discarding mode, discard this log.
23:40:19 info: BTLE BTLEBroadcaster.swift:217:peripheralManager(_:didReceiveRead:) – responding to read request with empty payload

**** TURNED ON AIRPORT MODE ON MY IPHONE HERE ****

23:42:16 info: Application AppDelegate.swift:198:applicationWillEnterForeground(_:) – Will Enter Foreground
2020-05-07 23:42:16.524522+0100 Sonar[784:192438] [AppCenter] WARNING: -[MSChannelUnitDefault enqueueItem:flags:]_block_invoke/141 Channel Analytics disabled in log discarding mode, discard this log.
23:42:16 info: Application AppDelegate.swift:187:applicationDidBecomeActive(_:) – Did Become Active

As you can see there's no discovery messages in the logs and on inspection the contactEvents.plist file was empty.

itspolly commented 4 years ago

As promised, here is the blog post explaining how the iOS <-> iOS workaround works. https://reincubate.com/blog/nhs-covid-19-background-tracing-details/

Should hopefully explain the behaviour you’ve been seeing.

lukeredpath commented 4 years ago

If I'm reading your blog post right, you're saying that, in order for scenario 3 in my tests above to work effectively it requires either:

If this is the case, that still means the scenario where any two iOS users with their phones locked in their pockets, who have not seen each other before and who are not in range of any Android devices, will still fail?

Also, if the issue seems related to the screen being off more than the app being in a background/suspended state, then where does that fit in to this?

itspolly commented 4 years ago

Providing the device has a managed to establish a connection with any device (whether it be Android or iOS), it appears as though the device is able to effectively poll as though it is in the foreground even when the device is locked.

If this is the case, that still means the scenario where any two iOS users with their phones locked in their pockets, who have not seen each other before and who are not in range of any Android devices, will still fail?

This would depend on the time it last saw an Android or iOS device, because there is a grace period before the app is suspended again (and thus falls back into limited BT-polling mode)

lukeredpath commented 4 years ago

OK, I will re-test scenario three with a third device tomorrow. Is this what you'd expect to see?

  1. iPad app in background, screen locked.
  2. Turn off Airplane mode on iPhone 1, leave app in background - discovery fails as per the above test.
  3. Turn off Airplane mode on iPhone 2 - still no discovery of this one yet.
  4. Bring app on iPhone 2 into foreground - iPad should discover iPhone 2 and iPhone 1?

And for completeness:

  1. iPad app in background, screen locked.
  2. Leave iPhone 1 in Airplane mode.
  3. Turn off Airplane mode on iPhone 2 and run the app so it is discovered by the iPad.
  4. Turn on Airplane mode on iPhone 2 to disconnect it from the iPad.
  5. Within some undefined window after this, turn off Airplane mode on iPhone 1 and it should be discovered?
Jeff-Stelling commented 4 years ago

So what happens with the app if no android devices are around to wakeup?

itspolly commented 4 years ago

@lukeredpath I’m not sure what I’d expect to see under those scenarios at the moment if I’m honest as I’m exhausted and have a headache (it’s all that reversing!). I’ll get back to you in the morning, but hey there’s no harm in trying.

itspolly commented 4 years ago

@Jeff-Stelling and there’s no other iOS devices around for it to talk to? The device would go silent until woken by an Android device

lukeredpath commented 4 years ago

For those interested in how the keep-alive works, it's effectively a ping-pong between the central/peripheral running on each device:

  1. After discovery, the central on each device subscribes to changes in the keep-alive characteristic of the other device's peripheral.

  2. Device 1 central (the listener) gets an RSSI ping from Device 2's peripheral and triggers the didReadRSSI delegate callback.

  3. Device 1 uses the above ping as a trigger to update the value of its the keep alive peripheral characteristic.

  4. Device 2 is notified of the change to Device 1's keep-alive value and triggers the didUpdateValueFor delegate callback where it in turn triggers an update of its keep-alive characteristic, notifying Device 1.

  5. The above process also happens in reverse, with Device 2 updating the its keep-alive value when when it gets an RSSI ping from Device 1 and Device 1 updating its keep-alive value when it receives the updated value from Device 2.

  6. There's some throttling in place to ensure each device only updates it's keep-alive value no more than every 8 seconds.

Thanks to Jamie for his investigation into this. If the final conclusion is that a) the behaviour I'm seeing is indeed a genuine issue and b) the workaround is as Jamie describes then I'm not very confident it will be an effective workaround, although I do applaud whoever came up with it because it's probably the best possible workaround you could manage. I hope in wide-scale testing I'm proved wrong (although if you're hoping this approach is abandoned completely in favour of the decentralised Apple/Google solution, then perhaps you're hoping I'm right).

deathchurch commented 4 years ago

What happens when Apple fix this bug that allows Android devices to wake background processes on iOS, this is clearly a battery drain and should be fixed?

chriswunsch00 commented 4 years ago

What happens when Apple fix this bug that allows Android devices to wake background processes on iOS, this is clearly a battery drain and should be fixed?

Yeah, if only Apple and Google had provided a proper solution to this problem ...

mrjcgoodwin commented 4 years ago

What happens when Apple fix this bug that allows Android devices to wake background processes on iOS, this is clearly a battery drain and should be fixed?

Read through this thread, the whole time thinking exactly that. Surely Apple are gonna close the workaround.

lukeredpath commented 4 years ago

If Jamie is right then it’s not just Android devices that are the key to this - the idea is that any other device actively scanning for the service UUID should in theory wake the locked device - so Android devices or other unlocked iPhones. I don’t have any Android to test but will test this with an unlocked iPhone later. It’s hard to say if this is a bug in iOS or just expected behaviour.

thoutbeckers commented 4 years ago

It's not a "workaround" or "bug", it's using a legitimate Apple Framework that allows your app to function as a peripheral.

This functionality is not limited to use by Android phones, it's also used by other iOS devices (where the app is running in the foreground) to detect the advertising iPhone . Hence why an iOS app that is open can also act as a bridge between two devices where the app is in the background. "Fixing" this could break many other apps that use this for good reasons.

The difference is in how iOS chooses to advertise services (requiring an extra step to discover them) and how it scans for peripherals in foreground (taking the extra step) vs background (just passively listening without taking the extra step).

thoutbeckers commented 4 years ago

Of course the Exposure Notification framework from Apple and Google fixes this by advertising the relevant service without requiring any extra steps to discover it. The method is uses to do this is not available for regular apps.

Since the privacy preserving features from that framework or not compatible with the backend architecture of the NHS it will not be useable however for this app.

jdmwood commented 4 years ago

@thoutbeckers it absolutely is a workaround if you're using an API in the manner that the owners didn't intend. I can't believe Apple intended the peripheral API (something intended for communicating with devices) to be constantly scanning in the background. If they did, they wouldn't have put in the restriction in the first place. Apple absolutely don't care about breaking existing apps if they feel the user experience of their customers (battery life, security) is an issue.

nrbrook commented 4 years ago

Firstly, a good way to understand the behaviour of the App is to use PacketLogger (available in additional tools for Xcode), connect to one device (must have Bluetooth profile installed), and filter on "85bf" (the start of the identifier characteristic, which must be read when one device is discovering another). In this way you can determine if the released App is working in a given scenario.

If there is an Android in range it will wake the iOS App most of the time (unless advertising has been stopped by iOS after 1h50m of inactivity). However, it seems there is a bug in this which will prevent the Android App discovering iOS devices that have multiple background advertisements, although that is easily fixed.

The way the Android App discovers the iOS App is the way backgrounded advertising in iOS works, and preventing it would mean breaking the functionality between iOS devices. But I could see Apple going this far, because they are very careful about this stuff.

My testing showed that the one scenario it won't work is when there are only iOS devices in range and screens are off. Even tapping the screen to wake it is sufficient for the devices to communicate. People use their phones a lot, and there is probably an Android phone around most of the time, but this is one place where it will fail some of the time.

Another scenario is if the screen is on and the App has been in the background for a long time (>1h50m, perhaps overnight) then it will not reconnect to another backgrounded iOS device. There must be no Android phones in range for this to occur. I witnessed this with two iOS devices with the App were in range overnight. Presumably this is because the screens were off and so the Apps were not able to discover and connect to each other, so eventually the iOS background scanning/advertising timeout was triggered. If either device had been woken up before the timeout it may have been sufficient to refresh the App. iOS seems to give it 6540 seconds (1h50m) of background advertising time.

In summary it might work "well enough", but some contacts will definitely be missed. Will they accept that and continue anyway because the data they can obtain is "more useful"? Or will they switch to the Apple-Google model being standardised in several other countries in Europe? It seems like they may be reconsidering their position...

thoutbeckers commented 4 years ago

@jdmwood2 That's true, but unintentional usage of an API would lead to an Appstore rejection, not a removal or "fix" of that API.

There are many (especially -but not only- background related) APIs that can be abused. You have to opt-in to them to use them, after which Apple is supposed to review if your usage is justified.

Apple seems to have chosen to allow this usage. Of course they can change their mind at a later point.

jdmwood commented 4 years ago

@thoutbeckers I've found Apple's approval process to be mercurial and inconsistent so under normal circumstances I wouldn't count on passing being a explicit approval. Having said that, this a high profile app so we'd hope they'd dig a bit deeper then usual. And yes, they might change their mind either intentionally or as a side effect of unrelated fixes

lukeredpath commented 4 years ago

Apple of course have regularly approved apps only to reject them in a subsequent update.

I think it’s reasonable to say that the background peripheral functionality is being used in a way that is unintended - whether you’d go as far as saying it’s being misused or abused is down to Apple.

The background execution guide clearly states that a background app acting as a peripheral does not broadcast its service UUID in the advertising packet and is therefore only intended to be discovered by other iOS devices actively scanning for that service UUID (in the foreground). The fact that this keep-alive and the reverse engineering of the advertising packet for Android is necessary shows it’s not really intended usage - iOS apps aren’t really intended to spend all day advertising and scanning for others.

lukeredpath commented 4 years ago

It’s also true to say that using the exposure notification API that Apple are working on isn’t a “fix” for this problem except for in a roundabout way. This could only be used with a complete switch from a centralised to a decentralised model which is a bit more work than simply swapping out the Bluetooth code. The two approaches are fundamentally incompatible with each other.

nrbrook commented 4 years ago

From Apple's docs:

  • Apps should be session based and provide an interface that allows the user to decide when to start and stop the delivery of Bluetooth-related events.
  • Upon being woken up, an app has around 10 seconds to complete a task. Ideally, it should complete the task as fast as possible and allow itself to be suspended again. Apps that spend too much time executing in the background can be throttled back by the system or killed.
  • Apps should not use being woken up as an opportunity to perform extraneous tasks that are unrelated to why the app was woken up by the system.

This App seems to fall foul of all of these, because of the keep alive mechanism which is an extraneous task that is unrelated to the reason it was woken up. But Apple does use its descretion with some Apps, and turns a blind eye. Particularly in this case you could see them continuing to let it slide unless it is having a significant impact on battery life. I imagine they will be actively testing that now.

thoutbeckers commented 4 years ago

Rejecting you or me with a poorly written brief note is not something that will happen to the NHS I imagine. Also, it's pretty much known they are in contact, I can hardly imagine this being unknown to Apple.

I would more worry that the technical solution itself is far from sufficient. It's reliance on connecting devices (rather than just scanning them) will easily work in testing a situation with a few devices, but will likely fail with dozen of devices around you. Android devices will not properly handle dozens of simultaneous connection requests.

The lack of any support/documentation for automating testing such a scenario in the client strongly suggests to me it has not been done.

lukeredpath commented 4 years ago

@nrbrook good to hear somebody else has been able to reproduce the third scenario in my testing above - it definitely seems related to a combination of the all being in the background and the device power stage. Were you testing on two iPhones? If so that rules out any possibility of me using an iOS affecting the test.

The issue with the advertising stopping completely after a period of time is concerning - it’s not something I’ve tested for but seems like yet another potential issue that could lead to missed exposure events.

The of course there’s the question of whether or not relying on the RSSI and TxPower of the devices as a measure of distance will even work correctly in the real world especially when there are obstacles and lots of other devices in the vicinity - imagine two people in a crowded train station. This is an issue regardless of what framework and approach you use.

Ultimately none of us can be sure how big of an impact this will have on the reliability of the overall process without real world testing - nobody has done this before. I’m just concerned that by that point it’s too late and any goodwill you might have had with getting the public to use this will be lost.

If they pull the plug on this app later and go with the decentralised approach (which isn’t without its challenges either) will it be too late to make a difference?

nrbrook commented 4 years ago

@lukeredpath I was testing with iPads and an iPhone, but I don't think the iOS background implementation is any different on iPad vs iPhone.

It is difficult to do "real world testing" with this, even in a small area like the Isle of Wight, even if you can get a good proportion of the population to install it, and even if people are still not too scared to go outside for the test to be useful. @thoutbeckers They could and should be doing automated testing yes, although perhaps have simply not had the time yet, based on the dates in the files they have only been building this for a month.

Ultimately this is a hacky solution and nothing is going to beat using Apple-Google's solution in terms of reliability. They are taking a real risk trying to roll their own, particularly if they are putting any kind of weight on it working successfully. However, I imagine they could just swap out the entire Bluetooth infrastructure in the current App with the Apple framework if (when?) they decide that will be a better route, so users would not need to install a different App.

sanvean commented 4 years ago

So to summarize this thread NHSX have spent a month with GCHQ's help building a series workaround/hacks to the iOS <-> iOS backgrounding issue hoping Apple will give them a pass on background/keep-alive abuse (which they'll probably get) but without actually solving the problem? Anyone who's actually tried to build a cross-platform (iOS + Android) Bluetooth based app (I have) could have told them this right from the start and I'm sure the GCHQ engineers did.

Knowing this they've then assumed they'll get still mass adoption on something storing every UK citizen's data centrally and whilst also reducing battery level on their phones?

At least someone seems to have finally seen sense:

https://www.theguardian.com/technology/2020/may/07/uk-may-ditch-nhs-contact-tracing-app-for-apple-and-google-model

but the mind actually boggles at the decision making process on this project.

Please give up on the workaround / hacks and switch to the Apple + Google API's - the app may have half a chance of a) working reliably in the first place and b) being adopted.

chriswunsch00 commented 4 years ago

So to summarize this thread NHSX have spent a month with GCHQ's help building a series workaround/hacks to the iOS <-> iOS backgrounding issue hoping Apple will keep them a pass on background/keep-alive abuse (which they'll probably get) but without actually solving the problem? Anyone who's actually tried to build a cross-platform (iOS + Android) Bluetooth based app (I have) could have told them this right from the start and I'm sure the GCHQ engineers did.

Knowing this they've then assumed they'll get still mass adoption on something storing every UK citizen's data centrally and whilst also reducing battery level on their phones?

At least someone seems to have finally seen sense:

https://www.theguardian.com/technology/2020/may/07/uk-may-ditch-nhs-contact-tracing-app-for-apple-and-google-model

but the mind actually boggles at the decision making process on this project.

Please give up on the workaround / hacks and switch to the Apple + Google API's - the app may have half a chance of a) working reliably in the first place and b) being adopted.

An admirably succinct summary.

nrbrook commented 4 years ago

@sanvean yes, it seems that way. I imagine the engineers got excited about the prospect of trying to hack around limitations, NCSC just focussed on the security aspect, politicians and scientists wanted the data, and nobody stopped to think "Is this actually the best way to save lives?"

chriswunsch00 commented 4 years ago

Too busy asking themselves ‘can we do this’ and never stopped to ask, ‘should we do this ?’

chriswunsch00 commented 4 years ago

I understand the lust for the data as I imagine it’ll be incredibly useful. In my opinion it’s usefulness doesn’t outweigh the risk of sacrificing users privacy. I don’t believe privacy should be a commodity and the longer we allow it, the worse it’ll become.

sanvean commented 4 years ago

@sanvean yes, it seems that way. I imagine the engineers got excited about the prospect of trying to hack around limitations, NCSC just focussed on the security aspect, politicians wanted the data, and nobody was pragmatic enough to say "Is this actually the best way to save lives?"

Yeah I'm sure some hubris mixed in with the classic tech mindset of there's got to be a workaround along with no doubt some key decision maker somewhere objecting to be told what to do by Apple + Google (I wager that was a politician though not the development team).

No doubt that Big Tech currently hold far too much sway and power in the modern world but is right here, right now really the time to tackle that problem?

nrbrook commented 4 years ago

@sanvean In this situation the fact there are only two players in the mobile space meant that they could come together and quickly deliver a solution. Thankfully the solution they have developed is privacy preserving. Ideally, this should have had democratic and expert oversight too, because Apple and Google are effectively dictating how one of the main tools to get out of this crisis will work for the whole world.

lukeredpath commented 4 years ago

I’m a bit concerned the thread is going a bit off-topic - I appreciate the discussion around whether or not the centralised approach and rolling their own was the right approach to take is an important one to have but would be good if we could keep this issue focussed on the technical problem raised.

sanvean commented 4 years ago

Hi Luke,

Yes I guess it has but the issue is that there isn't a reliable solution to the problem you've identified (even keep-alive workarounds) which is exactly why other countries have abandoned this approach. It's not actually a debate on the centralised vs. decentralised approach - the discovery method will not work reliably for iOS <-> iOS background discovery.

Apologies if I'm coming across as strongly opinated on the topic, it's because a) I have actually built an app attempting to solve a similar problem cross platform (think Happn but using Bluetooth) and b) my mother is currently working on the NHS Frontline and directly impacted by the decision making on this project.

Anyways, I very much appreciate the effort here by you on investigating the app in-depth and highlighting this technical issue to the dev team, as I was planning to spend today doing the same now the code was open source as I couldn't believe they'd figured out a way to solve the problem unless Apple had changed something - they haven't based on your analysis.

lukeredpath commented 4 years ago

Thanks - your input has still been very helpful. I’m still hopeful we might get some input from either the devs or decision makers on this issue - if the code is going to be open-sourced this way then it has to be expected that people will raise issues for discussion and I hope that they are able to engage with us.

sanvean commented 4 years ago

Thanks - your input has still been very helpful. I’m still hopeful we might get some input from either the devs or decision makers on this issue - if the code is going to be open-sourced this way then it has to be expected that people will raise issues for discussion and I hope that they are able to engage with us.

I couldn't agree more and I applaud your efforts here. However, if there is no real response or solution presented in the coming days I honestly think this thread will need to be published or shared more widely until it does receive the attention it deserves.

This is not a normal Issue you have raised here, the UK's economic recovery and lives are at stake. The app needs to work reliably in all common circumstances and as you have clearly highlighted -it doesn't currently.

stephenheron commented 4 years ago

Thanks to everyone for their hard work looking into this. It was one of my biggest questions when I heard about the app so it has been great to see everyone dig into the code and piece it together.

I put together a quick matrix showing the possible situations and where it works/doesn't work based on this issue. Does it look correct? I was getting a bit confused with all the possible scenarios, hopefully if it is correct then it will be useful for other folks to understand the limitations.

btle-matrix
jdmwood commented 4 years ago

Nice work all!

I would also just add that beyond the fact that the app definitely seems to not work in the case shown in the above matrix (nice summary @stephenheron ), it's also worth challenging whether it will work in practice even for the green blocks in that matrix.

I've tried to capture my thoughts in a comment in #7 (not sure if that was the best place). But in brief, will using devices as a peripheral actually work when there are dozens of devices all making concurrent connections with each other (sounds like a exponential problem to me). Will my device stop connecting if > N people are nearby? How will ancient Android devices loaded with manufacturer bloatware cope?

The peripheral API was not presumably designed for this, unlike, say iBeacon (though as others have pointed out, that would still suffer from even worse iOS backround issues).