diff --git a/android/app/src/main/java/com/naviapp/app/ApplicationStateManager.kt b/android/app/src/main/java/com/naviapp/app/ApplicationStateManager.kt deleted file mode 100644 index 2d0232d7dc..0000000000 --- a/android/app/src/main/java/com/naviapp/app/ApplicationStateManager.kt +++ /dev/null @@ -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() -} diff --git a/android/app/src/main/java/com/naviapp/app/initializers/NetworkStatsInitializer.kt b/android/app/src/main/java/com/naviapp/app/initializers/NetworkStatsInitializer.kt deleted file mode 100644 index 6bd1525253..0000000000 --- a/android/app/src/main/java/com/naviapp/app/initializers/NetworkStatsInitializer.kt +++ /dev/null @@ -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() - } -} diff --git a/android/app/src/main/java/com/naviapp/common/di/AppModule.kt b/android/app/src/main/java/com/naviapp/common/di/AppModule.kt index 53a0447a43..6a68eb7fce 100644 --- a/android/app/src/main/java/com/naviapp/common/di/AppModule.kt +++ b/android/app/src/main/java/com/naviapp/common/di/AppModule.kt @@ -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 { return listOf( @@ -74,7 +72,6 @@ object AppModule { networkConfigurationInitializer, signalManagerInitializer, lottieInitializer, - networkStatsInitializer, trustedTimeClientInitializer, ) } diff --git a/android/navi-common/src/main/java/com/navi/common/checkmate/core/CheckMateManager.kt b/android/navi-common/src/main/java/com/navi/common/checkmate/core/CheckMateManager.kt index 9b33b8f478..bfbcc7a8d0 100644 --- a/android/navi-common/src/main/java/com/navi/common/checkmate/core/CheckMateManager.kt +++ b/android/navi-common/src/main/java/com/navi/common/checkmate/core/CheckMateManager.kt @@ -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(), diff --git a/android/navi-common/src/main/java/com/navi/common/firebaseremoteconfig/FirebaseRemoteConfigHelper.kt b/android/navi-common/src/main/java/com/navi/common/firebaseremoteconfig/FirebaseRemoteConfigHelper.kt index 1025f183ae..b715405e5f 100644 --- a/android/navi-common/src/main/java/com/navi/common/firebaseremoteconfig/FirebaseRemoteConfigHelper.kt +++ b/android/navi-common/src/main/java/com/navi/common/firebaseremoteconfig/FirebaseRemoteConfigHelper.kt @@ -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" diff --git a/android/navi-common/src/main/java/com/navi/common/resourcemanager/ResourceDownloadWorker.kt b/android/navi-common/src/main/java/com/navi/common/resourcemanager/ResourceDownloadWorker.kt index 02a86b7e58..40005fbf27 100644 --- a/android/navi-common/src/main/java/com/navi/common/resourcemanager/ResourceDownloadWorker.kt +++ b/android/navi-common/src/main/java/com/navi/common/resourcemanager/ResourceDownloadWorker.kt @@ -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() } } diff --git a/android/navi-common/src/main/java/com/navi/common/resourcemanager/ResourceManagerUseCase.kt b/android/navi-common/src/main/java/com/navi/common/resourcemanager/ResourceManagerUseCase.kt index 7eb2e8bccd..e66461d8cb 100644 --- a/android/navi-common/src/main/java/com/navi/common/resourcemanager/ResourceManagerUseCase.kt +++ b/android/navi-common/src/main/java/com/navi/common/resourcemanager/ResourceManagerUseCase.kt @@ -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, diff --git a/android/navi-common/src/main/java/com/navi/common/resourcemanager/manager/ResourceManager.kt b/android/navi-common/src/main/java/com/navi/common/resourcemanager/manager/ResourceManager.kt index f838789e2b..7b2a13675a 100644 --- a/android/navi-common/src/main/java/com/navi/common/resourcemanager/manager/ResourceManager.kt +++ b/android/navi-common/src/main/java/com/navi/common/resourcemanager/manager/ResourceManager.kt @@ -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() } diff --git a/android/navi-common/src/main/java/com/navi/common/utils/Constants.kt b/android/navi-common/src/main/java/com/navi/common/utils/Constants.kt index 0ce348a44b..7a5c97a375 100644 --- a/android/navi-common/src/main/java/com/navi/common/utils/Constants.kt +++ b/android/navi-common/src/main/java/com/navi/common/utils/Constants.kt @@ -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" diff --git a/android/navi-common/src/main/java/com/navi/common/utils/NetworkStats.kt b/android/navi-common/src/main/java/com/navi/common/utils/NetworkStats.kt deleted file mode 100644 index 7ab1d2ae01..0000000000 --- a/android/navi-common/src/main/java/com/navi/common/utils/NetworkStats.kt +++ /dev/null @@ -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() - 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 - } -} diff --git a/android/navi-common/src/main/java/com/navi/common/utils/Utility.kt b/android/navi-common/src/main/java/com/navi/common/utils/Utility.kt index 9e21f96b00..e5f79feb21 100644 --- a/android/navi-common/src/main/java/com/navi/common/utils/Utility.kt +++ b/android/navi-common/src/main/java/com/navi/common/utils/Utility.kt @@ -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()) { diff --git a/android/navi-common/src/main/res/xml/default_remote_config.xml b/android/navi-common/src/main/res/xml/default_remote_config.xml index e5892bf6a2..4c1b99e151 100644 --- a/android/navi-common/src/main/res/xml/default_remote_config.xml +++ b/android/navi-common/src/main/res/xml/default_remote_config.xml @@ -621,22 +621,6 @@ NAVI_GI_RETRY_POLICY_ENABLED false - - NETWORK_SPEED_CHECK_FREQUENCY - 1000 - - - LOW_NETWORK_SPEED_THRESHOLD - 0 - - - LOW_NETWORK_BANDWIDTH_THRESHOLD - 0 - - - LOW_NETWORK_SIGNAL_THRESHOLD - 0 - NAVI_PAY_GENERIC_OFFERS_TTL_IN_MILLIS 1800000