diff --git a/sentry-android-core/api/sentry-android-core.api b/sentry-android-core/api/sentry-android-core.api index adebedf2700..2e965ca6e27 100644 --- a/sentry-android-core/api/sentry-android-core.api +++ b/sentry-android-core/api/sentry-android-core.api @@ -282,7 +282,6 @@ public final class io/sentry/android/core/DeviceInfoUtil { public fun getSplitApksInfo ()Lio/sentry/android/core/ContextUtils$SplitApksInfo; public fun getTotalMemory ()Ljava/lang/Long; public static fun isCharging (Landroid/content/Intent;Lio/sentry/SentryOptions;)Ljava/lang/Boolean; - public static fun resetInstance ()V } public abstract class io/sentry/android/core/EnvelopeFileObserverIntegration : io/sentry/Integration, java/io/Closeable { diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/DeviceInfoUtil.java b/sentry-android-core/src/main/java/io/sentry/android/core/DeviceInfoUtil.java index d988cbd090e..397403ae9ad 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/DeviceInfoUtil.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/DeviceInfoUtil.java @@ -15,7 +15,6 @@ import android.os.SystemClock; import android.util.DisplayMetrics; import io.sentry.DateUtils; -import io.sentry.ISentryLifecycleToken; import io.sentry.SentryLevel; import io.sentry.SentryOptions; import io.sentry.android.core.internal.util.CpuInfoUtils; @@ -23,7 +22,6 @@ import io.sentry.android.core.internal.util.RootChecker; import io.sentry.protocol.Device; import io.sentry.protocol.OperatingSystem; -import io.sentry.util.AutoClosableReentrantLock; import java.io.File; import java.util.Calendar; import java.util.Collections; @@ -34,17 +32,10 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; @ApiStatus.Internal public final class DeviceInfoUtil { - @SuppressLint("StaticFieldLeak") - private static volatile DeviceInfoUtil instance; - - private static final @NotNull AutoClosableReentrantLock staticLock = - new AutoClosableReentrantLock(); - private final @NotNull Context context; private final @NotNull SentryAndroidOptions options; private final @NotNull BuildInfoProvider buildInfoProvider; @@ -80,19 +71,7 @@ public DeviceInfoUtil( @NotNull public static DeviceInfoUtil getInstance( final @NotNull Context context, final @NotNull SentryAndroidOptions options) { - if (instance == null) { - try (final @NotNull ISentryLifecycleToken ignored = staticLock.acquire()) { - if (instance == null) { - instance = new DeviceInfoUtil(ContextUtils.getApplicationContext(context), options); - } - } - } - return instance; - } - - @TestOnly - public static void resetInstance() { - instance = null; + return options.getOrCreateDeviceInfoUtil(context); } // we can get some inspiration here diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroidOptions.java b/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroidOptions.java index 615db97a28d..1a4f8483af8 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroidOptions.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroidOptions.java @@ -3,8 +3,10 @@ import android.app.Activity; import android.app.ActivityManager; import android.app.ApplicationExitInfo; +import android.content.Context; import io.sentry.Hint; import io.sentry.IScope; +import io.sentry.ISentryLifecycleToken; import io.sentry.ISpan; import io.sentry.Sentry; import io.sentry.SentryEvent; @@ -141,6 +143,8 @@ public final class SentryAndroidOptions extends SentryOptions { /** Enables or disables collecting of external storage context. */ private boolean collectExternalStorageContext = false; + private volatile @Nullable DeviceInfoUtil deviceInfoUtil; + /** * Controls how many seconds to wait for sending events in case there were Startup Crashes in the * previous run. Sentry SDKs normally send events from a background queue, but in the case of @@ -200,6 +204,18 @@ public final class SentryAndroidOptions extends SentryOptions { /** Enable or disable intent extras reporting for system event breadcrumbs. Default is false. */ private boolean enableSystemEventBreadcrumbsExtras = false; + @NotNull + DeviceInfoUtil getOrCreateDeviceInfoUtil(final @NotNull Context context) { + if (deviceInfoUtil == null) { + try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) { + if (deviceInfoUtil == null) { + deviceInfoUtil = new DeviceInfoUtil(ContextUtils.getApplicationContext(context), this); + } + } + } + return deviceInfoUtil; + } + public interface BeforeCaptureCallback { /** diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitInfoEventProcessorTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitInfoEventProcessorTest.kt index 7eaa269f39f..012013cafd5 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitInfoEventProcessorTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitInfoEventProcessorTest.kt @@ -197,7 +197,6 @@ class ApplicationExitInfoEventProcessorTest { @BeforeTest fun `set up`() { - DeviceInfoUtil.resetInstance() fixture.context = ApplicationProvider.getApplicationContext() } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/DefaultAndroidEventProcessorTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/DefaultAndroidEventProcessorTest.kt index fbcd20b99fb..eab6ceacc13 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/DefaultAndroidEventProcessorTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/DefaultAndroidEventProcessorTest.kt @@ -87,7 +87,6 @@ class DefaultAndroidEventProcessorTest { fun `set up`() { context = ApplicationProvider.getApplicationContext() AppState.getInstance().resetInstance() - DeviceInfoUtil.resetInstance() CpuInfoUtils.getInstance().clear() } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/DeviceInfoUtilTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/DeviceInfoUtilTest.kt index 49c828b551e..3cd9e079da9 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/DeviceInfoUtilTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/DeviceInfoUtilTest.kt @@ -15,7 +15,9 @@ import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull +import kotlin.test.assertNotSame import kotlin.test.assertNull +import kotlin.test.assertSame import org.junit.runner.RunWith import org.robolectric.annotation.Config @@ -32,7 +34,45 @@ class DeviceInfoUtilTest { .putExtra(BatteryManager.EXTRA_LEVEL, 75) .putExtra(BatteryManager.EXTRA_PLUGGED, 0) ) - DeviceInfoUtil.resetInstance() + } + + @Test + fun `same options reuse device info util`() { + val options = SentryAndroidOptions() + + val first = DeviceInfoUtil.getInstance(context, options) + val second = DeviceInfoUtil.getInstance(context, options) + + assertSame(first, second) + } + + @Test + fun `different options use isolated device info utils`() { + val enabledOptions = + SentryAndroidOptions().apply { + dataCollection.setUserInfo(true) + isCollectAdditionalContext = true + isEnableRootCheck = true + } + val disabledOptions = + SentryAndroidOptions().apply { + dataCollection.setUserInfo(false) + isCollectAdditionalContext = false + isEnableRootCheck = false + } + + val enabled = DeviceInfoUtil.getInstance(context, enabledOptions) + val disabled = DeviceInfoUtil.getInstance(context, disabledOptions) + val enabledDevice = enabled.collectDeviceInformation(true, false) + val disabledDevice = disabled.collectDeviceInformation(true, false) + + assertNotSame(enabled, disabled) + assertNotNull(enabledDevice.id) + assertNotNull(enabledDevice.storageSize) + assertNotNull(enabled.operatingSystem.isRooted) + assertNull(disabledDevice.id) + assertNull(disabledDevice.storageSize) + assertNull(disabled.operatingSystem.isRooted) } @Test diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt index 8c552a8b633..bd689c6a453 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt @@ -231,7 +231,6 @@ class InternalSentrySdkTest { fun `set up`() { Sentry.close() context = ApplicationProvider.getApplicationContext() - DeviceInfoUtil.resetInstance() } @Test