Skip to content

Commit eeeae5a

Browse files
Fix clock for session start time [VPNAND-1479].
1 parent f2faa34 commit eeeae5a

File tree

4 files changed

+27
-35
lines changed

4 files changed

+27
-35
lines changed

app/src/main/java/com/protonvpn/android/bus/TrafficUpdate.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ package com.protonvpn.android.bus
2121
import com.protonvpn.android.utils.ConnectionTools
2222

2323
class TrafficUpdate(
24-
val timestampMs: Long,
24+
val monotonicTimestampMs: Long,
2525
val sessionStartTimestampMs: Long,
2626
val downloadSpeed: Long,
2727
val uploadSpeed: Long,

app/src/main/java/com/protonvpn/android/di/AppModule.kt

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -309,19 +309,6 @@ object AppModule {
309309
vpnErrorHandler
310310
)
311311

312-
@Singleton
313-
@Provides
314-
fun provideTrafficMonitor(
315-
vpnStateMonitor: VpnStateMonitor,
316-
connectivityMonitor: ConnectivityMonitor,
317-
) = TrafficMonitor(
318-
ProtonApplication.getAppContext(),
319-
scope,
320-
SystemClock::elapsedRealtime,
321-
vpnStateMonitor,
322-
connectivityMonitor
323-
)
324-
325312
@Provides
326313
@Singleton
327314
fun provideDelegatedSnackManager() = DelegatedSnackManager(SystemClock::elapsedRealtime)

app/src/main/java/com/protonvpn/android/ui/home/vpn/VpnStateConnectedViewModel.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,21 +97,21 @@ class VpnStateConnectedViewModel @Inject constructor(
9797
// https://github.com/PhilJay/MPAndroidChart/issues/2506
9898
TrafficSpeedChartData(listOf(Entry(0f, 0f)), listOf(Entry(0f, 0f)))
9999
} else {
100-
val lastTimestampMs = updates.last().timestampMs
100+
val lastMonotonicTimestampMs = updates.last().monotonicTimestampMs
101101
TrafficSpeedChartData(
102102
uploadKpbsHistory = updates.map { update ->
103-
toEntry(update, lastTimestampMs) { it.uploadSpeed }
103+
toEntry(update, lastMonotonicTimestampMs) { it.uploadSpeed }
104104
},
105105
downloadKbpsHistory = updates.map { update ->
106-
toEntry(update, lastTimestampMs) { it.downloadSpeed }
106+
toEntry(update, lastMonotonicTimestampMs) { it.downloadSpeed }
107107
}
108108
)
109109
}
110110
}
111111

112-
private inline fun toEntry(update: TrafficUpdate, lastTimestampMs: Long, getter: (TrafficUpdate) -> Long) =
112+
private inline fun toEntry(update: TrafficUpdate, lastMonotonicTimestampMs: Long, getter: (TrafficUpdate) -> Long) =
113113
Entry(
114-
(update.timestampMs - lastTimestampMs).toFloat() / MILLIS_IN_SECOND,
114+
(update.monotonicTimestampMs - lastMonotonicTimestampMs).toFloat() / MILLIS_IN_SECOND,
115115
getter(update).toFloat() / BYTES_IN_KBYTE
116116
)
117117
}

app/src/main/java/com/protonvpn/android/utils/TrafficMonitor.kt

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,31 @@ import android.os.PowerManager
2626
import androidx.core.content.getSystemService
2727
import androidx.lifecycle.MutableLiveData
2828
import com.protonvpn.android.bus.TrafficUpdate
29+
import com.protonvpn.android.di.ElapsedRealtimeClock
30+
import com.protonvpn.android.di.WallClock
2931
import com.protonvpn.android.logging.LogCategory
3032
import com.protonvpn.android.logging.ProtonLogger
3133
import com.protonvpn.android.utils.AndroidUtils.registerBroadcastReceiver
32-
import com.protonvpn.android.vpn.ConnectivityMonitor
3334
import com.protonvpn.android.vpn.VpnState
3435
import com.protonvpn.android.vpn.VpnStateMonitor
36+
import dagger.hilt.android.qualifiers.ApplicationContext
3537
import kotlinx.coroutines.CoroutineScope
3638
import kotlinx.coroutines.Dispatchers
3739
import kotlinx.coroutines.Job
3840
import kotlinx.coroutines.delay
3941
import kotlinx.coroutines.launch
4042
import java.util.concurrent.TimeUnit
43+
import javax.inject.Inject
44+
import javax.inject.Singleton
4145
import kotlin.math.roundToLong
4246

43-
class TrafficMonitor constructor(
44-
val context: Context,
45-
val scope: CoroutineScope,
46-
val now: () -> Long,
47-
val vpnStateMonitor: VpnStateMonitor,
48-
private val connectivityMonitor: ConnectivityMonitor,
47+
@Singleton
48+
class TrafficMonitor @Inject constructor(
49+
@ApplicationContext private val context: Context,
50+
private val scope: CoroutineScope,
51+
@ElapsedRealtimeClock private val monotonicClock: () -> Long,
52+
@WallClock private val wallClock: () -> Long,
53+
private val vpnStateMonitor: VpnStateMonitor,
4954
) {
5055
companion object {
5156
const val TRAFFIC_HISTORY_LENGTH_S = 31L
@@ -60,7 +65,7 @@ class TrafficMonitor constructor(
6065
private var sessionUploaded = 0L
6166
private var lastTotalDownload = 0L
6267
private var lastTotalUpload = 0L
63-
private var lastTimestamp = 0L
68+
private var lastMonotonicTimestamp = 0L
6469

6570
private var updateJob: Job? = null
6671

@@ -88,13 +93,13 @@ class TrafficMonitor constructor(
8893
}
8994

9095
private fun resetSession() {
91-
lastTimestamp = now()
96+
lastMonotonicTimestamp = monotonicClock()
9297
lastTotalDownload = TrafficStats.getTotalRxBytes()
9398
lastTotalUpload = TrafficStats.getTotalTxBytes()
9499

95100
sessionDownloaded = 0L
96101
sessionUploaded = 0L
97-
sessionStart = lastTimestamp
102+
sessionStart = wallClock()
98103

99104
trafficStatus.value = TrafficUpdate(0, sessionStart, 0, 0, 0, 0, 0)
100105
trafficHistory.value = emptyList()
@@ -115,8 +120,8 @@ class TrafficMonitor constructor(
115120
if (updateJob == null) {
116121
updateJob = scope.launch(Dispatchers.Main) {
117122
while (true) {
118-
val timestamp = now()
119-
val elapsedMillis = timestamp - lastTimestamp
123+
val monotonicTimestamp = monotonicClock()
124+
val elapsedMillis = monotonicTimestamp - lastMonotonicTimestamp
120125
val elapsedSeconds = elapsedMillis / 1000f
121126

122127
// Speeds need to be divided by two due to TrafficStats calculating both phone and VPN
@@ -132,20 +137,20 @@ class TrafficMonitor constructor(
132137
sessionDownloaded += downloaded
133138
sessionUploaded += uploaded
134139

135-
val sessionTimeSeconds = (timestamp - sessionStart).toInt() / 1000
140+
val sessionTimeSeconds = (wallClock() - sessionStart).toInt() / 1000
136141
val update = TrafficUpdate(
137-
timestamp, sessionStart, downloadSpeed, uploadSpeed, sessionDownloaded,
142+
monotonicTimestamp, sessionStart, downloadSpeed, uploadSpeed, sessionDownloaded,
138143
sessionUploaded, sessionTimeSeconds
139144
)
140145
trafficStatus.value = update
141146
trafficHistory.value = (trafficHistory.value!! + update)
142147
.takeLastWhile {
143-
it.timestampMs > timestamp - TimeUnit.SECONDS.toMillis(TRAFFIC_HISTORY_LENGTH_S)
148+
it.monotonicTimestampMs > monotonicTimestamp - TimeUnit.SECONDS.toMillis(TRAFFIC_HISTORY_LENGTH_S)
144149
}
145150

146151
lastTotalDownload = totalDownload
147152
lastTotalUpload = totalUpload
148-
lastTimestamp = timestamp
153+
lastMonotonicTimestamp = monotonicTimestamp
149154

150155
delay(1000)
151156
}

0 commit comments

Comments
 (0)