Skip to content

Commit 52f7632

Browse files
authored
Merge branch 'main' into rz/feat/system-network-integrations-overloads
2 parents 8311e2f + b23af9e commit 52f7632

File tree

25 files changed

+317
-53
lines changed

25 files changed

+317
-53
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
### Fixes
1111

12+
- Avoid StrictMode warnings ([#4724](https://github.com/getsentry/sentry-java/pull/4724))
1213
- Use logger from options for JVM profiler ([#4771](https://github.com/getsentry/sentry-java/pull/4771))
1314
- Session Replay: Avoid deadlock when pausing replay if no connection ([#4788](https://github.com/getsentry/sentry-java/pull/4788))
1415

gradle/libs.versions.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ androidx-navigation-runtime = { module = "androidx.navigation:navigation-runtime
9191
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidxNavigation" }
9292
androidx-sqlite = { module = "androidx.sqlite:sqlite", version = "2.5.2" }
9393
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version = "1.2.1" }
94+
androidx-browser = { module = "androidx.browser:browser", version = "1.8.0" }
9495
coil-compose = { module = "io.coil-kt:coil-compose", version = "2.6.0" }
9596
commons-compress = {module = "org.apache.commons:commons-compress", version = "1.25.0"}
9697
context-propagation = { module = "io.micrometer:context-propagation", version = "1.1.0" }

sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import io.sentry.android.core.internal.modules.AssetsModulesLoader;
3131
import io.sentry.android.core.internal.util.AndroidConnectionStatusProvider;
3232
import io.sentry.android.core.internal.util.AndroidCurrentDateProvider;
33+
import io.sentry.android.core.internal.util.AndroidRuntimeManager;
3334
import io.sentry.android.core.internal.util.AndroidThreadChecker;
3435
import io.sentry.android.core.internal.util.SentryFrameMetricsCollector;
3536
import io.sentry.android.core.performance.AppStartMetrics;
@@ -108,7 +109,7 @@ static void loadDefaultAndMetadataOptions(
108109
final @NotNull BuildInfoProvider buildInfoProvider) {
109110
Objects.requireNonNull(context, "The context is required.");
110111

111-
context = ContextUtils.getApplicationContext(context);
112+
@NotNull final Context finalContext = ContextUtils.getApplicationContext(context);
112113

113114
Objects.requireNonNull(options, "The options object is required.");
114115
Objects.requireNonNull(logger, "The ILogger object is required.");
@@ -120,17 +121,22 @@ static void loadDefaultAndMetadataOptions(
120121
options.setDefaultScopeType(ScopeType.CURRENT);
121122
options.setOpenTelemetryMode(SentryOpenTelemetryMode.OFF);
122123
options.setDateProvider(new SentryAndroidDateProvider());
124+
options.setRuntimeManager(new AndroidRuntimeManager());
123125

124126
// set a lower flush timeout on Android to avoid ANRs
125127
options.setFlushTimeoutMillis(DEFAULT_FLUSH_TIMEOUT_MS);
126128

127129
options.setFrameMetricsCollector(
128-
new SentryFrameMetricsCollector(context, logger, buildInfoProvider));
130+
new SentryFrameMetricsCollector(finalContext, logger, buildInfoProvider));
129131

130-
ManifestMetadataReader.applyMetadata(context, options, buildInfoProvider);
131-
options.setCacheDirPath(getCacheDir(context).getAbsolutePath());
132+
ManifestMetadataReader.applyMetadata(finalContext, options, buildInfoProvider);
132133

133-
readDefaultOptionValues(options, context, buildInfoProvider);
134+
options.setCacheDirPath(
135+
options
136+
.getRuntimeManager()
137+
.runWithRelaxedPolicy(() -> getCacheDir(finalContext).getAbsolutePath()));
138+
139+
readDefaultOptionValues(options, finalContext, buildInfoProvider);
134140
AppState.getInstance().registerLifecycleObserver(options);
135141
}
136142

sentry-android-core/src/main/java/io/sentry/android/core/SentryPerformanceProvider.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020
import io.sentry.SentryOptions;
2121
import io.sentry.TracesSampler;
2222
import io.sentry.TracesSamplingDecision;
23+
import io.sentry.android.core.internal.util.AndroidRuntimeManager;
2324
import io.sentry.android.core.internal.util.SentryFrameMetricsCollector;
2425
import io.sentry.android.core.performance.AppStartMetrics;
2526
import io.sentry.android.core.performance.TimeSpan;
2627
import io.sentry.util.AutoClosableReentrantLock;
28+
import io.sentry.util.runtime.IRuntimeManager;
2729
import java.io.BufferedReader;
2830
import java.io.File;
2931
import java.io.FileInputStream;
@@ -108,7 +110,9 @@ private void launchAppStartProfiler(final @NotNull AppStartMetrics appStartMetri
108110
return;
109111
}
110112

111-
final @NotNull File cacheDir = AndroidOptionsInitializer.getCacheDir(context);
113+
final @NotNull IRuntimeManager runtimeManager = new AndroidRuntimeManager();
114+
final @NotNull File cacheDir =
115+
runtimeManager.runWithRelaxedPolicy(() -> AndroidOptionsInitializer.getCacheDir(context));
112116
final @NotNull File configFile = new File(cacheDir, APP_START_PROFILING_CONFIG_FILE_NAME);
113117

114118
// No config exists: app start profiling is not enabled

sentry-android-core/src/main/java/io/sentry/android/core/cache/AndroidEnvelopeCache.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.sentry.util.HintUtils;
2020
import io.sentry.util.Objects;
2121
import java.io.File;
22+
import java.io.FileNotFoundException;
2223
import java.io.FileOutputStream;
2324
import java.io.OutputStream;
2425
import org.jetbrains.annotations.ApiStatus;
@@ -157,18 +158,18 @@ public static boolean hasStartupCrashMarker(final @NotNull SentryOptions options
157158

158159
final File lastAnrMarker = new File(cacheDirPath, LAST_ANR_REPORT);
159160
try {
160-
if (lastAnrMarker.exists() && lastAnrMarker.canRead()) {
161-
final String content = FileUtils.readText(lastAnrMarker);
162-
// we wrapped into try-catch already
163-
//noinspection ConstantConditions
164-
return content.equals("null") ? null : Long.parseLong(content.trim());
165-
} else {
161+
final String content = FileUtils.readText(lastAnrMarker);
162+
// we wrapped into try-catch already
163+
//noinspection ConstantConditions
164+
return content.equals("null") ? null : Long.parseLong(content.trim());
165+
} catch (Throwable e) {
166+
if (e instanceof FileNotFoundException) {
166167
options
167168
.getLogger()
168169
.log(DEBUG, "Last ANR marker does not exist. %s.", lastAnrMarker.getAbsolutePath());
170+
} else {
171+
options.getLogger().log(ERROR, "Error reading last ANR marker", e);
169172
}
170-
} catch (Throwable e) {
171-
options.getLogger().log(ERROR, "Error reading last ANR marker", e);
172173
}
173174
return null;
174175
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.sentry.android.core.internal.util;
2+
3+
import android.os.StrictMode;
4+
import io.sentry.util.runtime.IRuntimeManager;
5+
import org.jetbrains.annotations.ApiStatus;
6+
import org.jetbrains.annotations.NotNull;
7+
8+
@ApiStatus.Internal
9+
public final class AndroidRuntimeManager implements IRuntimeManager {
10+
@Override
11+
public <T> T runWithRelaxedPolicy(final @NotNull IRuntimeManagerCallback<T> toRun) {
12+
final @NotNull StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
13+
final @NotNull StrictMode.VmPolicy oldVmPolicy = StrictMode.getVmPolicy();
14+
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX);
15+
StrictMode.setVmPolicy(StrictMode.VmPolicy.LAX);
16+
try {
17+
return toRun.run();
18+
} finally {
19+
StrictMode.setThreadPolicy(oldPolicy);
20+
StrictMode.setVmPolicy(oldVmPolicy);
21+
}
22+
}
23+
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ private CpuInfoUtils() {}
5151
if (!cpuDir.getName().matches("cpu[0-9]+")) continue;
5252
File cpuMaxFreqFile = new File(cpuDir, CPUINFO_MAX_FREQ_PATH);
5353

54-
if (!cpuMaxFreqFile.exists() || !cpuMaxFreqFile.canRead()) continue;
55-
5654
long khz;
5755
try {
5856
String content = FileUtils.readText(cpuMaxFreqFile);

sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import io.sentry.android.core.internal.debugmeta.AssetsDebugMetaLoader
2424
import io.sentry.android.core.internal.gestures.AndroidViewGestureTargetLocator
2525
import io.sentry.android.core.internal.modules.AssetsModulesLoader
2626
import io.sentry.android.core.internal.util.AndroidConnectionStatusProvider
27+
import io.sentry.android.core.internal.util.AndroidRuntimeManager
2728
import io.sentry.android.core.internal.util.AndroidThreadChecker
2829
import io.sentry.android.core.performance.AppStartMetrics
2930
import io.sentry.android.fragment.FragmentLifecycleIntegration
@@ -917,4 +918,10 @@ class AndroidOptionsInitializerTest {
917918
fixture.sentryOptions.compositePerformanceCollector is DefaultCompositePerformanceCollector
918919
}
919920
}
921+
922+
@Test
923+
fun `AndroidRuntimeManager is set in the options`() {
924+
fixture.initSut()
925+
assertIs<AndroidRuntimeManager>(fixture.sentryOptions.runtimeManager)
926+
}
920927
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package io.sentry.android.core.internal.util
2+
3+
import android.os.StrictMode
4+
import androidx.test.ext.junit.runners.AndroidJUnit4
5+
import kotlin.test.AfterTest
6+
import kotlin.test.Test
7+
import kotlin.test.assertEquals
8+
import kotlin.test.assertNotEquals
9+
import kotlin.test.assertTrue
10+
import org.junit.runner.RunWith
11+
12+
@RunWith(AndroidJUnit4::class)
13+
class AndroidRuntimeManagerTest {
14+
15+
val sut = AndroidRuntimeManager()
16+
17+
@AfterTest
18+
fun `clean up`() {
19+
// Revert StrictMode policies to avoid issues with other tests
20+
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX)
21+
StrictMode.setVmPolicy(StrictMode.VmPolicy.LAX)
22+
}
23+
24+
@Test
25+
fun `runWithRelaxedPolicy changes policy when running and restores it afterwards`() {
26+
var called = false
27+
val threadPolicy = StrictMode.ThreadPolicy.Builder().detectAll().penaltyDeath().build()
28+
val vmPolicy = StrictMode.VmPolicy.Builder().detectAll().penaltyDeath().build()
29+
assertNotEquals(StrictMode.ThreadPolicy.LAX, threadPolicy)
30+
assertNotEquals(StrictMode.VmPolicy.LAX, vmPolicy)
31+
32+
// Set and assert the StrictMode policies
33+
StrictMode.setThreadPolicy(threadPolicy)
34+
StrictMode.setVmPolicy(vmPolicy)
35+
assertEquals(threadPolicy.toString(), StrictMode.getThreadPolicy().toString())
36+
assertEquals(vmPolicy.toString(), StrictMode.getVmPolicy().toString())
37+
38+
// Run the function and assert LAX policies
39+
called =
40+
sut.runWithRelaxedPolicy {
41+
assertEquals(
42+
StrictMode.ThreadPolicy.LAX.toString(),
43+
StrictMode.getThreadPolicy().toString(),
44+
)
45+
assertEquals(StrictMode.VmPolicy.LAX.toString(), StrictMode.getVmPolicy().toString())
46+
true
47+
}
48+
49+
// Policies should be reverted back
50+
assertEquals(threadPolicy.toString(), StrictMode.getThreadPolicy().toString())
51+
assertEquals(vmPolicy.toString(), StrictMode.getVmPolicy().toString())
52+
53+
// Ensure the code ran
54+
assertTrue(called)
55+
}
56+
57+
@Test
58+
fun `runWithRelaxedPolicy changes policy and restores it afterwards even if the code throws`() {
59+
var called = false
60+
val threadPolicy = StrictMode.ThreadPolicy.Builder().detectAll().penaltyDeath().build()
61+
val vmPolicy = StrictMode.VmPolicy.Builder().detectAll().penaltyDeath().build()
62+
63+
// Set and assert the StrictMode policies
64+
StrictMode.setThreadPolicy(threadPolicy)
65+
StrictMode.setVmPolicy(vmPolicy)
66+
67+
// Run the function and assert LAX policies
68+
try {
69+
sut.runWithRelaxedPolicy {
70+
assertEquals(
71+
StrictMode.ThreadPolicy.LAX.toString(),
72+
StrictMode.getThreadPolicy().toString(),
73+
)
74+
assertEquals(StrictMode.VmPolicy.LAX.toString(), StrictMode.getVmPolicy().toString())
75+
called = true
76+
throw Exception("Test exception")
77+
}
78+
} catch (_: Exception) {}
79+
80+
// Policies should be reverted back
81+
assertEquals(threadPolicy.toString(), StrictMode.getThreadPolicy().toString())
82+
assertEquals(vmPolicy.toString(), StrictMode.getVmPolicy().toString())
83+
84+
// Ensure the code ran
85+
assertTrue(called)
86+
}
87+
}

sentry-android-integration-tests/sentry-uitest-android/src/androidTest/java/io/sentry/uitest/android/SdkInitTests.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.sentry.uitest.android
22

3+
import android.os.StrictMode
34
import androidx.lifecycle.Lifecycle
45
import androidx.test.core.app.launchActivity
56
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -252,6 +253,15 @@ class SdkInitTests : BaseUiTest() {
252253
assertDefaultIntegrations()
253254
}
254255

256+
@Test
257+
fun initNotThrowStrictMode() {
258+
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder().detectAll().penaltyDeath().build())
259+
StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder().detectAll().penaltyDeath().build())
260+
val sampleScenario = launchActivity<EmptyActivity>()
261+
initSentry()
262+
sampleScenario.moveToState(Lifecycle.State.DESTROYED)
263+
}
264+
255265
private fun assertDefaultIntegrations() {
256266
val integrations =
257267
mutableListOf(

0 commit comments

Comments
 (0)