@@ -44,6 +44,7 @@ final class ExposureManager: NSObject {
4444 private static let chaffBackgroundTaskIdentifier = " \( Bundle . main. bundleIdentifier!) .chaff "
4545 private static let exposureDetectionBackgroundTaskIdentifier = " \( Bundle . main. bundleIdentifier!) .exposure-notification "
4646 private static let deleteOldExposuresBackgroundTaskIdentifier = " \( Bundle . main. bundleIdentifier!) .delete-old-exposures "
47+ private static let enxMigrationBackgroundTaskIdentifier = " \( Bundle . main. bundleIdentifier!) .enx-migration "
4748
4849 @objc private( set) static var shared : ExposureManager ?
4950
@@ -100,6 +101,13 @@ final class ExposureManager: NSObject {
100101 name: . ChaffRequestTriggered,
101102 object: nil
102103 )
104+
105+ notificationCenter. addObserver (
106+ self ,
107+ selector: #selector( scheduleEnxBackgroundTaskIfNeeded) ,
108+ name: . EnxNotificationTriggered,
109+ object: nil
110+ )
103111 }
104112
105113 deinit {
@@ -183,6 +191,38 @@ final class ExposureManager: NSObject {
183191 return btSecureStorage. deleteSymptomLogEntries ( )
184192 }
185193
194+ //Notifies the user they need to migrate
195+ func notifyUserEnxIfNeeded( ) {
196+ let defaults = UserDefaults . standard
197+ let lastEnxTimestamp = defaults. double ( forKey: " lastEnxTimestamp " )
198+ let enxCount = defaults. double ( forKey: " enxCount " )
199+ let sameDay = self . hasBeenTwentyFourHours ( lastSubmitted: lastEnxTimestamp)
200+
201+ if ( lastEnxTimestamp == 0 || sameDay != nil ) {
202+ if ( enxCount <= 3 ) {
203+ let newDate = Date . init ( ) ;
204+ defaults. set ( enxCount + 1 , forKey: " enxCount " ) ;
205+ defaults. set ( newDate, forKey: " lastEnxTimestamp " ) ;
206+
207+ let identifier = String . enxMigrationIdentifier
208+ let content = UNMutableNotificationContent ( )
209+ content. title = String . enxMigrationNotificationTitle. localized
210+ content. body = String . enxMigrationNotificationContent. localized
211+ content. userInfo = [ String . notificationUrlKey: " \( String . notificationUrlBasePath) " ]
212+ content. sound = . default
213+
214+ let request = UNNotificationRequest ( identifier: identifier, content: content, trigger: nil )
215+ userNotificationCenter. add ( request) { error in
216+ DispatchQueue . main. async {
217+ if let error = error {
218+ print ( " Error showing error user notification: \( error) " )
219+ }
220+ }
221+ }
222+ }
223+ }
224+ }
225+
186226 ///Notifies the user to enable bluetooth to be able to exchange keys
187227 func notifyUserBlueToothOffIfNeeded( ) {
188228 let identifier = String . bluetoothNotificationIdentifier
@@ -222,6 +262,17 @@ final class ExposureManager: NSObject {
222262 } , callback: callback)
223263 }
224264
265+ @objc func registerEnxMigrationBackgroundTask( ) {
266+ bgTaskScheduler. register ( forTaskWithIdentifier: ExposureManager . enxMigrationBackgroundTaskIdentifier,
267+ using: . main) { [ weak self] task in
268+ //let state = UIApplication.shared.applicationState
269+ //if state == .background || state == .inactive {
270+ // background
271+ self ? . scheduleEnxBackgroundTaskIfNeeded ( )
272+ //}
273+ }
274+ }
275+
225276
226277 // MARK: == Exposure Detection ==
227278
@@ -236,6 +287,8 @@ final class ExposureManager: NSObject {
236287 // Notify the user if bluetooth is off
237288 strongSelf. notifyUserBlueToothOffIfNeeded ( )
238289
290+ strongSelf. notifyUserEnxIfNeeded ( )
291+
239292 // Perform the exposure detection
240293 let progress = strongSelf. detectExposures { result in
241294 switch result {
@@ -277,7 +330,7 @@ final class ExposureManager: NSObject {
277330 let randomNum = Int . random ( in: 0 ..< 20 )
278331 let lastChaffTimestamp = defaults. double ( forKey: " lastChaffTimestamp " )
279332
280- if ( ( lastChaffTimestamp == 0 || ( ( self ? . hasBeenTwentyFourHours ( lastSubmittedChaff : lastChaffTimestamp) ) != nil ) ) && ( randomNum > 8 && randomNum < 19 ) ) {
333+ if ( ( lastChaffTimestamp == 0 || ( ( self ? . hasBeenTwentyFourHours ( lastSubmitted : lastChaffTimestamp) ) != nil ) ) && ( randomNum > 8 && randomNum < 19 ) ) {
281334 self ? . performChaffRequest ( )
282335 }
283336 }
@@ -304,12 +357,23 @@ final class ExposureManager: NSObject {
304357 /**
305358 Checks to see if it has been twenty four hours since the last chaff submission.
306359 */
307- func hasBeenTwentyFourHours( lastSubmittedChaff : Double ) -> Bool {
308- let timeComparison = Date . init ( timeIntervalSinceNow: lastSubmittedChaff )
360+ func hasBeenTwentyFourHours( lastSubmitted : Double ) -> Bool {
361+ let timeComparison = Date . init ( timeIntervalSinceNow: lastSubmitted )
309362 let twentyFourHoursAgo = Date . init ( timeIntervalSinceNow: - 3600 * 24 )
310363 return timeComparison >= twentyFourHoursAgo
311364 }
312365
366+ @objc func scheduleEnxBackgroundTaskIfNeeded( ) {
367+ guard manager. exposureNotificationStatus == . active else { return }
368+ let taskRequest = BGProcessingTaskRequest ( identifier: ExposureManager . enxMigrationBackgroundTaskIdentifier)
369+ taskRequest. requiresNetworkConnectivity = false
370+ do {
371+ try bgTaskScheduler. submit ( taskRequest)
372+ } catch {
373+ print ( " Unable to schedule background task: \( error) " )
374+ }
375+ }
376+
313377 @objc func scheduleExposureDetectionBackgroundTaskIfNeeded( ) {
314378 guard manager. exposureNotificationStatus == . active else { return }
315379 let taskRequest = BGProcessingTaskRequest ( identifier: ExposureManager . exposureDetectionBackgroundTaskIdentifier)
0 commit comments