NTP-67490 || deleted traffic stats code (#16341)

This commit is contained in:
Aman S
2025-05-27 18:37:23 +05:30
committed by GitHub
parent 09d8cf5a96
commit c01272a075
12 changed files with 9 additions and 306 deletions

View File

@@ -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()
}

View File

@@ -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()
}
}

View File

@@ -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,
)
}

View File

@@ -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(),

View File

@@ -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"

View File

@@ -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()
}
}

View File

@@ -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,

View File

@@ -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()
}

View File

@@ -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"

View File

@@ -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
}
}

View File

@@ -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()) {

View File

@@ -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>