Skip to content

Commit 5fca96a

Browse files
authored
[COASTAL-969] System time offset detected (#516)
* report when system time offset is detected * removed SystemTimeOffsetDetector protocol * provide a time interval instead of an indicator
1 parent 3efadb7 commit 5fca96a

File tree

3 files changed

+35
-4
lines changed

3 files changed

+35
-4
lines changed

Loop/Managers/DeviceDataManager.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ final class DeviceDataManager {
211211

212212
private(set) var pumpManagerHUDProvider: HUDProvider?
213213

214+
private var trustedTimeChecker: TrustedTimeChecker
215+
214216
// MARK: - WatchKit
215217

216218
private var watchManager: WatchDataManager!
@@ -231,7 +233,8 @@ final class DeviceDataManager {
231233
closedLoopStatus: ClosedLoopStatus,
232234
cacheStore: PersistenceController,
233235
localCacheDuration: TimeInterval,
234-
overrideHistory: TemporaryScheduleOverrideHistory)
236+
overrideHistory: TemporaryScheduleOverrideHistory,
237+
trustedTimeChecker: TrustedTimeChecker)
235238
{
236239

237240
let fileManager = FileManager.default
@@ -310,6 +313,8 @@ final class DeviceDataManager {
310313
// HealthStorePreferredGlucoseUnitDidChange will be notified once the user completes the health access form. Set to .milligramsPerDeciliter until then
311314
displayGlucoseUnitObservable = DisplayGlucoseUnitObservable(displayGlucoseUnit: glucoseStore.preferredUnit ?? .milligramsPerDeciliter)
312315

316+
self.trustedTimeChecker = trustedTimeChecker
317+
313318
if let pumpManagerRawValue = rawPumpManager ?? UserDefaults.appGroup?.legacyPumpManagerRawValue {
314319
pumpManager = pumpManagerFromRawValue(pumpManagerRawValue)
315320
// Update lastPumpEventsReconciliation on DoseStore
@@ -1682,3 +1687,7 @@ extension DeviceDataManager {
16821687
}
16831688

16841689
extension DeviceDataManager: DeviceStatusProvider {}
1690+
1691+
extension DeviceDataManager {
1692+
var detectedSystemTimeOffset: TimeInterval { trustedTimeChecker.detectedSystemTimeOffset }
1693+
}

Loop/Managers/LoopAppManager.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ class LoopAppManager: NSObject {
175175
closedLoopStatus: closedLoopStatus,
176176
cacheStore: cacheStore,
177177
localCacheDuration: localCacheDuration,
178-
overrideHistory: overrideHistory
178+
overrideHistory: overrideHistory,
179+
trustedTimeChecker: trustedTimeChecker
179180
)
180181
settingsManager.deviceStatusProvider = deviceDataManager
181182

Loop/Managers/TrustedTimeChecker.swift

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import UIKit
1313
fileprivate extension UserDefaults {
1414
private enum Key: String {
1515
case lastSignificantTimeChangeAlert = "com.loopkit.Loop.LastSignificantTimeChangeAlert"
16+
case detectedSystemTimeOffset = "com.loopkit.Loop.DetectedSystemTimeOffset"
1617
}
1718

1819
var lastSignificantTimeChangeAlert: Date? {
@@ -23,6 +24,15 @@ fileprivate extension UserDefaults {
2324
set(newValue, forKey: Key.lastSignificantTimeChangeAlert.rawValue)
2425
}
2526
}
27+
28+
var detectedSystemTimeOffset: TimeInterval? {
29+
get {
30+
return object(forKey: Key.detectedSystemTimeOffset.rawValue) as? TimeInterval
31+
}
32+
set {
33+
set(newValue, forKey: Key.detectedSystemTimeOffset.rawValue)
34+
}
35+
}
2636
}
2737

2838
class TrustedTimeChecker {
@@ -34,6 +44,12 @@ class TrustedTimeChecker {
3444
private weak var alertManager: AlertManager?
3545
private lazy var log = DiagnosticLog(category: "TrustedTimeChecker")
3646

47+
var detectedSystemTimeOffset: TimeInterval {
48+
didSet {
49+
UserDefaults.standard.detectedSystemTimeOffset = detectedSystemTimeOffset
50+
}
51+
}
52+
3753
init(alertManager: AlertManager) {
3854
ntpClient = TrueTimeClient.sharedInstance
3955
#if DEBUG
@@ -43,6 +59,7 @@ class TrustedTimeChecker {
4359
#endif
4460
ntpClient.start()
4561
self.alertManager = alertManager
62+
self.detectedSystemTimeOffset = UserDefaults.standard.detectedSystemTimeOffset ?? 0
4663
NotificationCenter.default.addObserver(forName: UIApplication.significantTimeChangeNotification,
4764
object: nil, queue: nil) { [weak self] _ in self?.checkTrustedTime() }
4865
NotificationCenter.default.addObserver(forName: .LoopRunning,
@@ -56,12 +73,16 @@ class TrustedTimeChecker {
5673
case let .success(referenceTime):
5774
let deviceNow = Date()
5875
let ntpNow = referenceTime.now()
59-
let timeDelta = abs(ntpNow.timeIntervalSince(deviceNow))
76+
let timeDelta = ntpNow.timeIntervalSince(deviceNow)
6077
let timeSinceLastAlert = abs(ntpNow.timeIntervalSince(UserDefaults.standard.lastSignificantTimeChangeAlert ?? Date.distantPast))
61-
if timeDelta > self.acceptableTimeDelta, timeSinceLastAlert > self.minimumAlertFrequency {
78+
79+
if abs(timeDelta) > self.acceptableTimeDelta, timeSinceLastAlert > self.minimumAlertFrequency {
6280
self.log.info("applicationSignificantTimeChange: ntpNow = %@, deviceNow = %@", ntpNow.debugDescription, deviceNow.debugDescription)
6381
self.issueTimeChangedAlert()
82+
self.detectedSystemTimeOffset = timeDelta
6483
UserDefaults.standard.lastSignificantTimeChangeAlert = ntpNow
84+
} else {
85+
self.detectedSystemTimeOffset = 0
6586
}
6687
case let .failure(error):
6788
self.log.error("applicationSignificantTimeChange: Error getting NTP time: %@", error.localizedDescription)

0 commit comments

Comments
 (0)