NTP-67490 || deleted traffic stats code (#16341)
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.naviapp.app
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.annotation.CallSuper
|
||||
import com.navi.common.NaviActivityLifecycleCallbacks
|
||||
|
||||
/**
|
||||
* A base class to manage and monitor the lifecycle of activities in the application and determine
|
||||
* whether the app is in the foreground (at least one activity is visible to the user) or in the
|
||||
* background (all activities are stopped).
|
||||
*
|
||||
* Key Features:
|
||||
* - Keeps track of the number of active (started) activities using `foregroundActivitiesCount`.
|
||||
* - Detects transitions between foreground and background states and invokes appropriate abstract
|
||||
* methods (`onForeground()` and `onBackground()`) for subclasses to implement.
|
||||
*
|
||||
* Usage:
|
||||
* - Subclasses should implement the `onForeground()` and `onBackground()` methods to define custom
|
||||
* behavior when the application enters the foreground or background, respectively.
|
||||
* - Call `initStateManager()` to register lifecycle callbacks.
|
||||
*
|
||||
* Note:
|
||||
* - This class uses `NaviActivityLifecycleCallbacks`, which is a custom implementation of
|
||||
* `Application.ActivityLifecycleCallbacks`.
|
||||
*/
|
||||
abstract class ApplicationStateManager {
|
||||
|
||||
private var isInitialized = false
|
||||
private var foregroundActivitiesCount = 0
|
||||
|
||||
@CallSuper
|
||||
fun initStateManager(application: NaviApplication) {
|
||||
application.registerActivityLifecycleCallbacks(activityLifecycleCallback)
|
||||
}
|
||||
|
||||
val activityLifecycleCallback =
|
||||
object : NaviActivityLifecycleCallbacks() {
|
||||
|
||||
override fun onActivityStarted(activity: Activity) {
|
||||
foregroundActivitiesCount++
|
||||
|
||||
if (!isInitialized) {
|
||||
isInitialized = true
|
||||
onForeground()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityStopped(activity: Activity) {
|
||||
foregroundActivitiesCount--
|
||||
|
||||
if (foregroundActivitiesCount == 0) {
|
||||
isInitialized = false
|
||||
onBackground()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun onForeground()
|
||||
|
||||
abstract fun onBackground()
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024-2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.naviapp.app.initializers
|
||||
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.NETWORK_SPEED_CHECK_FREQUENCY
|
||||
import com.navi.common.utils.NetworkStats
|
||||
import com.naviapp.app.ApplicationStateManager
|
||||
import com.naviapp.app.NaviApplication
|
||||
import javax.inject.Inject
|
||||
|
||||
class NetworkStatsInitializer @Inject constructor() :
|
||||
ApplicationStateManager(), ComponentInitializer {
|
||||
private val networkStatsCheckFrequency: Long by lazy {
|
||||
FirebaseRemoteConfigHelper.getLong(NETWORK_SPEED_CHECK_FREQUENCY)
|
||||
}
|
||||
|
||||
override fun initialize(application: NaviApplication) {
|
||||
super.initStateManager(application)
|
||||
}
|
||||
|
||||
override fun onForeground() {
|
||||
NetworkStats.startTracking(updateIntervalMs = networkStatsCheckFrequency)
|
||||
}
|
||||
|
||||
override fun onBackground() {
|
||||
NetworkStats.stopTracking()
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ import com.naviapp.app.initializers.ComponentInitializer
|
||||
import com.naviapp.app.initializers.CrashHandlerInitializer
|
||||
import com.naviapp.app.initializers.LottieInitializer
|
||||
import com.naviapp.app.initializers.NetworkConfigurationInitializer
|
||||
import com.naviapp.app.initializers.NetworkStatsInitializer
|
||||
import com.naviapp.app.initializers.SdkInitializer
|
||||
import com.naviapp.app.initializers.SignalManagerInitializer
|
||||
import com.naviapp.app.initializers.TrustedTimeClientInitializer
|
||||
@@ -63,7 +62,6 @@ object AppModule {
|
||||
networkConfigurationInitializer: NetworkConfigurationInitializer,
|
||||
signalManagerInitializer: SignalManagerInitializer,
|
||||
lottieInitializer: LottieInitializer,
|
||||
networkStatsInitializer: NetworkStatsInitializer,
|
||||
trustedTimeClientInitializer: TrustedTimeClientInitializer,
|
||||
): List<ComponentInitializer> {
|
||||
return listOf(
|
||||
@@ -74,7 +72,6 @@ object AppModule {
|
||||
networkConfigurationInitializer,
|
||||
signalManagerInitializer,
|
||||
lottieInitializer,
|
||||
networkStatsInitializer,
|
||||
trustedTimeClientInitializer,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ package com.navi.common.checkmate.core
|
||||
|
||||
import com.navi.analytics.utils.AlfredFacade
|
||||
import com.navi.analytics.utils.NaviTrackEvent
|
||||
import com.navi.base.AppServiceManager
|
||||
import com.navi.base.bandwidthbuddy.BandwidthAccessor
|
||||
import com.navi.base.utils.orZero
|
||||
import com.navi.common.checkmate.model.EventType
|
||||
@@ -23,8 +22,6 @@ import com.navi.common.checkmate.utils.getIsNae
|
||||
import com.navi.common.constants.VERTICAL
|
||||
import com.navi.common.network.models.GenericResponse
|
||||
import com.navi.common.network.models.RepoResult
|
||||
import com.navi.common.utils.NetworkStats
|
||||
import com.navi.common.utils.getDownloadNetworkStrength
|
||||
import retrofit2.Response
|
||||
|
||||
object CheckMateManager {
|
||||
@@ -90,9 +87,6 @@ object CheckMateManager {
|
||||
"alfredSessionId" to AlfredFacade.getAlfredSessionId(),
|
||||
"signalLevel" to NaviTrackEvent.signalInfo.level.toString(),
|
||||
"signalType" to NaviTrackEvent.signalInfo.type.name,
|
||||
"maxBandwidth" to
|
||||
getDownloadNetworkStrength(AppServiceManager.application).toString(),
|
||||
"networkSpeed" to NetworkStats.networkSpeed.toString(),
|
||||
"isNae" to
|
||||
getIsNae(isNae = isNae, statusCode = statusCode, exception = exception)
|
||||
.toString(),
|
||||
|
||||
@@ -152,10 +152,6 @@ object FirebaseRemoteConfigHelper {
|
||||
const val LITMUS_EXPERIMENTS_CACHE_DURATION_IN_MILLIS =
|
||||
"LITMUS_EXPERIMENTS_CACHE_DURATION_IN_MILLIS"
|
||||
const val NAVI_PAY_INTENT_ACTIVITY_CHECK_ENABLED = "NAVI_PAY_INTENT_ACTIVITY_CHECK_ENABLED"
|
||||
const val NETWORK_SPEED_CHECK_FREQUENCY = "NETWORK_SPEED_CHECK_FREQUENCY"
|
||||
const val LOW_NETWORK_SIGNAL_THRESHOLD = "LOW_NETWORK_SIGNAL_THRESHOLD"
|
||||
const val LOW_NETWORK_BANDWIDTH_THRESHOLD = "LOW_NETWORK_BANDWIDTH_THRESHOLD"
|
||||
const val LOW_NETWORK_SPEED_THRESHOLD = "LOW_NETWORK_SPEED_THRESHOLD"
|
||||
const val API_RETRY_COUNT = "API_RETRY_COUNT"
|
||||
const val DATA_UPLOAD_CHECK_ENABLED = "DATA_UPLOAD_CHECK_ENABLED"
|
||||
const val LOCATION_FETCH_MIN_INTERVAL_IN_MILLIS = "LOCATION_FETCH_MIN_INTERVAL_IN_MILLIS"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * Copyright © 2024-2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
@@ -24,7 +24,7 @@ constructor(@ApplicationContext val context: Context, workerParameters: WorkerPa
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
NaviTrackEvent.trackEvent(INIT_RESOURCE_DOWNLOAD_WORKER)
|
||||
resourceManagerUseCase.execute(context, 1)
|
||||
resourceManagerUseCase.execute(1)
|
||||
return Result.success()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ package com.navi.common.resourcemanager
|
||||
import android.content.Context
|
||||
import com.navi.alfred.utils.orZero
|
||||
import com.navi.analytics.utils.NaviTrackEvent
|
||||
import com.navi.bandwidthbuddy.BandwidthQuality
|
||||
import com.navi.base.bandwidthbuddy.BandwidthAccessor
|
||||
import com.navi.common.resourcemanager.db.ResourceManagerDatabase
|
||||
import com.navi.common.resourcemanager.db.dao.ResourceDao
|
||||
import com.navi.common.resourcemanager.db.model.ResourceEntity
|
||||
@@ -19,7 +21,6 @@ import com.navi.common.resourcemanager.manager.ResourceManager.exceptionHandler
|
||||
import com.navi.common.resourcemanager.model.IconData
|
||||
import com.navi.common.resourcemanager.repository.ResourceManagerRepository
|
||||
import com.navi.common.resourcemanager.resourceDownloader.ResourceDownloadManagerImpl
|
||||
import com.navi.common.resourcemanager.util.enum.ConnectionQuality
|
||||
import com.navi.common.resourcemanager.util.enum.ResourceType
|
||||
import com.navi.common.utils.Constants.AUDIO_EXTENSTION
|
||||
import com.navi.common.utils.Constants.BUCKET_SIZE
|
||||
@@ -30,7 +31,6 @@ import com.navi.common.utils.Constants.RESOURCE_DOWNLOAD_BUCKET
|
||||
import com.navi.common.utils.Constants.SVG_EXTENSION
|
||||
import com.navi.common.utils.EMPTY
|
||||
import com.navi.common.utils.endsWithAny
|
||||
import com.navi.common.utils.getDownloadNetworkStrength
|
||||
import dagger.hilt.android.EntryPointAccessors
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
@@ -68,15 +68,15 @@ class ResourceManagerUseCase @Inject constructor(@ApplicationContext context: Co
|
||||
cacheResource = CacheResource(context, this)
|
||||
}
|
||||
|
||||
suspend fun execute(context: Context, priority: Int?) {
|
||||
suspend fun execute(priority: Int?) {
|
||||
setDownloadCounter(0)
|
||||
scope.launch { initialiseResourceDownloadUseCase(context, priority) }.join()
|
||||
scope.launch { initialiseResourceDownloadUseCase(priority) }.join()
|
||||
}
|
||||
|
||||
private suspend fun initialiseResourceDownloadUseCase(context: Context, priority: Int?) {
|
||||
private suspend fun initialiseResourceDownloadUseCase(priority: Int?) {
|
||||
downloadCounter.collect { downloadCounter ->
|
||||
if (downloadCounter == 0) {
|
||||
if (getNetworkQuality(context) == ConnectionQuality.GOOD) {
|
||||
if (BandwidthAccessor.networkQuality == BandwidthQuality.GOOD) {
|
||||
val bucket = repository.fetchResourceBucket(priority = priority)
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
RESOURCE_DOWNLOAD_BUCKET,
|
||||
@@ -150,19 +150,6 @@ class ResourceManagerUseCase @Inject constructor(@ApplicationContext context: Co
|
||||
}
|
||||
}
|
||||
|
||||
private fun getNetworkQuality(context: Context): ConnectionQuality {
|
||||
val speed = getDownloadNetworkStrength(context)
|
||||
// Convert the network strength from KBps (kilobytes per second) to Kbps (kilobits per
|
||||
// second)
|
||||
// as we are using the thresholds in Kbps here.
|
||||
val speedInKbps = speed * 8f
|
||||
return when (speedInKbps) {
|
||||
in 0f..500f -> ConnectionQuality.POOR
|
||||
in 501f..1000f -> ConnectionQuality.MODERATE
|
||||
else -> ConnectionQuality.GOOD
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun onResourceDownloadSuccess(
|
||||
url: String,
|
||||
status: Boolean,
|
||||
|
||||
@@ -75,7 +75,7 @@ object ResourceManager : Closeable {
|
||||
|
||||
private suspend fun initResourceDownload(context: Context, isCriticalFlow: Boolean) {
|
||||
if (!isCriticalFlow) {
|
||||
resourceManagerUseCase.execute(context = context, priority = 0)
|
||||
resourceManagerUseCase.execute(priority = 0)
|
||||
} else {
|
||||
resourceManagerUseCase.close()
|
||||
}
|
||||
|
||||
@@ -335,13 +335,6 @@ object Constants {
|
||||
const val IS_SUCCESS = "is_success"
|
||||
const val RETRY_COUNT = "retry_count"
|
||||
|
||||
const val NETWORK_SPEED_TRACKING_EXCEPTION = "dev_network_speed_tracking_exception"
|
||||
const val NETWORK_SPEED_THRESHOLD_REACHED = "dev_network_speed_threshold_reached"
|
||||
const val NETWORK_BANDWIDTH_THRESHOLD_REACHED = "dev_network_bandwidth_threshold_reached"
|
||||
const val NETWORK_SIGNAL_STRENGTH_THRESHOLD_REACHED =
|
||||
"dev_network_signal_strength_threshold_reached"
|
||||
const val NO_NETWORK_THRESHOLDS_REACHED = "dev_no_network_thresholds_reached"
|
||||
|
||||
// navi pay common cache keys
|
||||
const val NAVI_PAY_REWARDS_NUDGE_CACHE_KEY = "naviPayRewardsNudge"
|
||||
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.common.utils
|
||||
|
||||
import android.net.TrafficStats
|
||||
import com.navi.analytics.utils.NaviTrackEvent
|
||||
import com.navi.common.utils.Constants.NETWORK_SPEED_TRACKING_EXCEPTION
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
object NetworkStats {
|
||||
var networkSpeed: Float = -1f
|
||||
private val speedHistory = mutableListOf<Float>()
|
||||
private const val SMOOTHING_WINDOW = 5
|
||||
private var trackingJob: Job? = null
|
||||
private var isTracking = false
|
||||
|
||||
private val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
|
||||
if (isTracking) {
|
||||
stopTracking()
|
||||
}
|
||||
NaviTrackEvent.trackEvent(
|
||||
eventName = NETWORK_SPEED_TRACKING_EXCEPTION,
|
||||
eventValues = mapOf("coroutineException" to exception.message.orEmpty()),
|
||||
)
|
||||
exception.log()
|
||||
}
|
||||
|
||||
private fun getTotalReceptionBytes(): Long {
|
||||
try {
|
||||
return TrafficStats.getTotalRxBytes()
|
||||
} catch (e: Exception) {
|
||||
stopTracking()
|
||||
NaviTrackEvent.trackEvent(
|
||||
eventName = NETWORK_SPEED_TRACKING_EXCEPTION,
|
||||
eventValues = mapOf("exception" to e.message.orEmpty()),
|
||||
)
|
||||
e.log()
|
||||
return -1L
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts tracking the network download speed in bytes per second (Bps) and updates it
|
||||
* periodically.
|
||||
*
|
||||
* @param updateIntervalMs The interval in milliseconds at which the network speed is updated.
|
||||
* Default is 1000ms (1 second).
|
||||
*
|
||||
* Functionality:
|
||||
* - Continuously calculates the instantaneous network speed based on data received over time.
|
||||
* - Maintains a history of recent speeds, smoothing the speed value using a rolling average
|
||||
* over the last `SMOOTHING_WINDOW` values.
|
||||
* - Updates the `networkSpeed` variable with the averaged speed in real-time.
|
||||
* - Uses `TrafficStats.getTotalRxBytes()` to measure total bytes received since device boot.
|
||||
*
|
||||
* Guardrails and Precautions:
|
||||
* - Prevents multiple instances of tracking using the `isTracking` flag.
|
||||
* - Checks if `TrafficStats` is unsupported on the device; exits early if so.
|
||||
* - Handles exceptions gracefully and logs them via `NaviAnalyticsHelper.recordException`.
|
||||
*
|
||||
* Notes:
|
||||
* - Runs on a coroutine in the `Dispatchers.IO` context to avoid blocking the main thread.
|
||||
*/
|
||||
fun startTracking(updateIntervalMs: Long = 1000L) {
|
||||
if (
|
||||
isTracking ||
|
||||
getTotalReceptionBytes() == TrafficStats.UNSUPPORTED.toLong() ||
|
||||
updateIntervalMs <= 0
|
||||
)
|
||||
return
|
||||
isTracking = true
|
||||
|
||||
var previousRxBytes = getTotalReceptionBytes()
|
||||
var previousTime = System.currentTimeMillis()
|
||||
|
||||
trackingJob =
|
||||
CoroutineScope(Dispatchers.IO + coroutineExceptionHandler).launch {
|
||||
while (isTracking) {
|
||||
val currentTime = System.currentTimeMillis()
|
||||
val elapsedTime = (currentTime - previousTime) / 1000f
|
||||
val currentRxBytes = getTotalReceptionBytes()
|
||||
if (currentRxBytes == -1L) {
|
||||
return@launch
|
||||
}
|
||||
val downloadedBytes = currentRxBytes - previousRxBytes
|
||||
val instantaneousSpeed =
|
||||
(downloadedBytes / elapsedTime).takeIf { elapsedTime > 0 } ?: 0f
|
||||
speedHistory.add(instantaneousSpeed)
|
||||
if (speedHistory.size > SMOOTHING_WINDOW) {
|
||||
speedHistory.removeAt(0)
|
||||
}
|
||||
networkSpeed =
|
||||
speedHistory.takeIf { it.isNotEmpty() }?.average()?.toFloat() ?: 0f
|
||||
previousTime = currentTime
|
||||
previousRxBytes = currentRxBytes
|
||||
delay(updateIntervalMs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun stopTracking() {
|
||||
isTracking = false
|
||||
trackingJob?.cancel()
|
||||
trackingJob = null
|
||||
speedHistory.clear()
|
||||
networkSpeed = -1f
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import android.content.Context.RECEIVER_NOT_EXPORTED
|
||||
import android.content.IntentFilter
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.net.ConnectivityManager
|
||||
import android.os.Build
|
||||
import android.os.UserManager
|
||||
import android.view.View
|
||||
@@ -29,7 +28,6 @@ import androidx.compose.ui.platform.SoftwareKeyboardController
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.getSystemService
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.navi.alfred.utils.log
|
||||
import com.navi.analytics.utils.NaviTrackEvent
|
||||
import com.navi.base.AppServiceManager
|
||||
import com.navi.base.deeplink.util.DeeplinkConstants
|
||||
@@ -410,32 +408,6 @@ fun copyToClipboard(
|
||||
Toast.makeText(context, toastText, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the estimated maximum downstream bandwidth of the current network connection.
|
||||
*
|
||||
* @param context The application context used to access the ConnectivityManager service.
|
||||
* @return The downstream bandwidth in kilo Bytes per second (KBps) as a Float. Returns 0f if the
|
||||
* bandwidth cannot be determined or an exception occurs.
|
||||
*
|
||||
* Note:
|
||||
* - The bandwidth always only refers to the estimated transport bandwidth for the first hop.
|
||||
* - If an exception occurs during retrieval, it is logged and 0f is returned.
|
||||
* - This method uses `linkDownstreamBandwidthKbps` from `NetworkCapabilities` to get the bandwidth.
|
||||
*/
|
||||
fun getDownloadNetworkStrength(context: Context): Float {
|
||||
try {
|
||||
val connectivityManager =
|
||||
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
val networkCapabilities =
|
||||
connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
|
||||
val networkBandwidth = networkCapabilities?.linkDownstreamBandwidthKbps?.toFloat() ?: 0f
|
||||
return networkBandwidth / 8f
|
||||
} catch (e: Exception) {
|
||||
e.log()
|
||||
}
|
||||
return 0f
|
||||
}
|
||||
|
||||
fun DestinationsNavigator.navigateUp(activity: Activity) {
|
||||
val navigationUpSuccess = popBackStack()
|
||||
if (navigationUpSuccess.not()) {
|
||||
|
||||
@@ -621,22 +621,6 @@
|
||||
<key>NAVI_GI_RETRY_POLICY_ENABLED</key>
|
||||
<value>false</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>NETWORK_SPEED_CHECK_FREQUENCY</key>
|
||||
<value>1000</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>LOW_NETWORK_SPEED_THRESHOLD</key>
|
||||
<value>0</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>LOW_NETWORK_BANDWIDTH_THRESHOLD</key>
|
||||
<value>0</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>LOW_NETWORK_SIGNAL_THRESHOLD</key>
|
||||
<value>0</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>NAVI_PAY_GENERIC_OFFERS_TTL_IN_MILLIS</key>
|
||||
<value>1800000</value>
|
||||
|
||||
Reference in New Issue
Block a user