Skip to content

Commit c7698bc

Browse files
committed
cache is now updated directly if not on the main thread
while cache is updated, if no cache data exists, connection status is unknown and type is null
1 parent f358548 commit c7698bc

File tree

2 files changed

+88
-9
lines changed

2 files changed

+88
-9
lines changed

sentry-android-core/src/main/java/io/sentry/android/core/internal/util/AndroidConnectionStatusProvider.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,12 @@ private boolean isNetworkEffectivelyConnected(
147147
: ConnectionStatus.DISCONNECTED;
148148
}
149149

150+
// If cache is being updated, and there's no cached data, return UNKNOWN status until cache is
151+
// updated
152+
if (isUpdatingCache.get()) {
153+
return ConnectionStatus.UNKNOWN;
154+
}
155+
150156
// Fallback to legacy method when NetworkCapabilities not available
151157
final ConnectivityManager connectivityManager =
152158
getConnectivityManager(context, options.getLogger());
@@ -164,6 +170,12 @@ private boolean isNetworkEffectivelyConnected(
164170
return getConnectionType(capabilities);
165171
}
166172

173+
// If cache is being updated, and there's no cached data, return UNKNOWN status until cache is
174+
// updated
175+
if (isUpdatingCache.get()) {
176+
return null;
177+
}
178+
167179
// Fallback to legacy method when NetworkCapabilities not available
168180
return getConnectionType(context, options.getLogger(), buildInfoProvider);
169181
}
@@ -402,24 +414,24 @@ private void updateCache() {
402414
@RequiresApi(api = Build.VERSION_CODES.M)
403415
private void updateCacheFromConnectivityManager() {
404416
final ConnectivityManager connectivityManager =
405-
getConnectivityManager(context, options.getLogger());
417+
getConnectivityManager(context, options.getLogger());
406418
if (connectivityManager != null) {
407419
final @Nullable NetworkCapabilities capabilities =
408-
getNetworkCapabilities(connectivityManager);
420+
getNetworkCapabilities(connectivityManager);
409421

410422
try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) {
411423
cachedNetworkCapabilities = capabilities;
412424
lastCacheUpdateTime = timeProvider.getCurrentTimeMillis();
413425

414426
if (capabilities != null) {
415427
options
416-
.getLogger()
417-
.log(
418-
SentryLevel.DEBUG,
419-
"Cache updated - Status: "
420-
+ getConnectionStatusFromCache()
421-
+ ", Type: "
422-
+ getConnectionTypeFromCache());
428+
.getLogger()
429+
.log(
430+
SentryLevel.DEBUG,
431+
"Cache updated - Status: "
432+
+ getConnectionStatusFromCache()
433+
+ ", Type: "
434+
+ getConnectionTypeFromCache());
423435
}
424436
}
425437
}

sentry-android-core/src/test/java/io/sentry/android/core/internal/util/AndroidConnectionStatusProviderTest.kt

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ import io.sentry.android.core.AppState
2525
import io.sentry.android.core.BuildInfoProvider
2626
import io.sentry.android.core.ContextUtils
2727
import io.sentry.android.core.SystemEventsBreadcrumbsIntegration
28+
import io.sentry.test.DeferredExecutorService
2829
import io.sentry.test.ImmediateExecutorService
2930
import io.sentry.transport.ICurrentDateProvider
31+
import io.sentry.util.thread.IThreadChecker
3032
import kotlin.test.AfterTest
3133
import kotlin.test.BeforeTest
3234
import kotlin.test.Test
@@ -38,6 +40,7 @@ import kotlin.test.assertTrue
3840
import org.junit.runner.RunWith
3941
import org.mockito.MockedStatic
4042
import org.mockito.Mockito.mockStatic
43+
import org.mockito.Mockito.never
4144
import org.mockito.kotlin.any
4245
import org.mockito.kotlin.anyOrNull
4346
import org.mockito.kotlin.argThat
@@ -205,6 +208,41 @@ class AndroidConnectionStatusProviderTest {
205208
providerWithNullConnectivity.close()
206209
}
207210

211+
@Test
212+
fun `When cache is updating, return UNKNOWN for connectionStatus on main thread`() {
213+
whenever(networkInfo.isConnected).thenReturn(true)
214+
// When we are on the main thread
215+
val mockThreadChecker = mock<IThreadChecker>()
216+
options.threadChecker = mockThreadChecker
217+
whenever(mockThreadChecker.isMainThread()).thenReturn(true)
218+
219+
// The update is done on the background
220+
val executorService = DeferredExecutorService()
221+
options.executorService = executorService
222+
223+
// Advance time beyond TTL (2 minutes)
224+
currentTime += 2 * 60 * 1000L
225+
226+
// Connection status is unknown while we update the cache
227+
assertEquals(
228+
IConnectionStatusProvider.ConnectionStatus.UNKNOWN,
229+
connectionStatusProvider.connectionStatus,
230+
)
231+
232+
verify(connectivityManager, never()).activeNetworkInfo
233+
verify(connectivityManager, never()).activeNetwork
234+
235+
// When background cache update is done
236+
executorService.runAll()
237+
238+
// Connection status is updated
239+
verify(connectivityManager).activeNetwork
240+
assertEquals(
241+
IConnectionStatusProvider.ConnectionStatus.CONNECTED,
242+
connectionStatusProvider.connectionStatus,
243+
)
244+
}
245+
208246
@Test
209247
fun `When there's no permission, return null for getConnectionType`() {
210248
whenever(contextMock.checkPermission(any(), any(), any())).thenReturn(PERMISSION_DENIED)
@@ -219,6 +257,35 @@ class AndroidConnectionStatusProviderTest {
219257
assertNull(connectionStatusProvider.connectionType)
220258
}
221259

260+
@Test
261+
fun `When cache is updating, return null for getConnectionType on main thread`() {
262+
whenever(networkInfo.isConnected).thenReturn(true)
263+
// When we are on the main thread
264+
val mockThreadChecker = mock<IThreadChecker>()
265+
options.threadChecker = mockThreadChecker
266+
whenever(mockThreadChecker.isMainThread()).thenReturn(true)
267+
268+
// The update is done on the background
269+
val executorService = DeferredExecutorService()
270+
options.executorService = executorService
271+
272+
// Advance time beyond TTL (2 minutes)
273+
currentTime += 2 * 60 * 1000L
274+
275+
// Connection type is null while we update the cache
276+
assertNull(connectionStatusProvider.connectionType)
277+
278+
verify(connectivityManager, never()).activeNetworkInfo
279+
verify(connectivityManager, never()).activeNetwork
280+
281+
// When background cache update is done
282+
executorService.runAll()
283+
284+
// Connection type is updated
285+
verify(connectivityManager).activeNetwork
286+
assertNotNull(connectionStatusProvider.connectionType)
287+
}
288+
222289
@Test
223290
fun `When network capabilities are not available, return null for getConnectionType`() {
224291
whenever(connectivityManager.getNetworkCapabilities(any())).thenReturn(null)

0 commit comments

Comments
 (0)