From b27d61d218059360b2d9482e87a79b6bac6aeeae Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Fri, 24 Jul 2026 15:00:13 +0200 Subject: [PATCH] fix(android): Apply user info policy to distinct ID Generate the default Android installation ID after programmatic configuration and only when the resolved user information policy allows it. Preserve custom distinct IDs and keep legacy behavior when Data Collection is absent. Refs #5666 Co-Authored-By: Claude --- .../core/AndroidOptionsInitializer.java | 8 ---- .../io/sentry/android/core/SentryAndroid.java | 8 ++++ .../core/AndroidOptionsInitializerTest.kt | 44 +++++++++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java b/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java index 9cc5cb3df0f..2a60e5750d7 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java @@ -471,14 +471,6 @@ private static void readDefaultOptionValues( options.addInAppInclude(packageName); } } - - if (options.getDistinctId() == null) { - try { - options.setDistinctId(Installation.id(context)); - } catch (RuntimeException e) { - options.getLogger().log(SentryLevel.ERROR, "Could not generate distinct Id.", e); - } - } } /** diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java b/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java index f27259fd635..150569dcecf 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java @@ -149,6 +149,14 @@ public static void init( "Error in the 'OptionsConfiguration.configure' callback.", t); } + if (options.getDistinctId() == null + && options.getDataCollectionResolver().isUserInfoWithLegacyAlways()) { + try { + options.setDistinctId(Installation.id(context)); + } catch (RuntimeException e) { + options.getLogger().log(SentryLevel.ERROR, "Could not generate distinct Id.", e); + } + } // if SentryPerformanceProvider was disabled or removed, // we set the app start / sdk init time here instead diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt index f8724d286f8..068b0964bcc 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt @@ -111,6 +111,12 @@ class AndroidOptionsInitializerTest { ) sentryOptions.configureOptions() + if ( + sentryOptions.distinctId == null && + sentryOptions.dataCollectionResolver.isUserInfoWithLegacyAlways + ) { + sentryOptions.distinctId = Installation.id(if (useRealContext) context else mockContext) + } AndroidOptionsInitializer.initializeIntegrationsAndProcessors( sentryOptions, if (useRealContext) context else mockContext, @@ -349,6 +355,44 @@ class AndroidOptionsInitializerTest { installation.deleteOnExit() } + @Test + fun `init should not set generated distinct id when user info is disabled`() { + fixture.initSut(configureOptions = { dataCollection.setUserInfo(false) }) + + assertNull(fixture.sentryOptions.distinctId) + } + + @Test + fun `init should set generated distinct id when user info is enabled`() { + fixture.initSut(configureOptions = { dataCollection.setUserInfo(true) }) + + assertNotNull(fixture.sentryOptions.distinctId) + } + + @Test + fun `init should preserve explicit distinct id when user info is disabled`() { + fixture.initSut( + configureOptions = { + dataCollection.setUserInfo(false) + distinctId = "custom-id" + } + ) + + assertEquals("custom-id", fixture.sentryOptions.distinctId) + } + + @Test + fun `init should set generated distinct id when explicit value is null`() { + fixture.initSut( + configureOptions = { + dataCollection.setUserInfo(true) + distinctId = null + } + ) + + assertNotNull(fixture.sentryOptions.distinctId) + } + @Test fun `init should set proguard uuid id on start`() { fixture.initSut(