From fd0bb3bc85c594b138c0ee33b5bb9b90bc45e531 Mon Sep 17 00:00:00 2001 From: Nelson Osacky Date: Fri, 6 Nov 2026 13:28:24 +0100 Subject: [PATCH] fix(android): Resolve NullAway findings in sentry-android-core NullAway never ran on sentry-android-core. Enabling it reports 32 errors. Most are fields and return types that are nullable but not annotated, and fields NullAway cannot see as checked because a check happens in a different scope (a lambda, another method) than the dereference. - Annotate the nullable fields and return types, including ViewHierarchyNode.setType and UiElement.equals in the sentry module. - Read options once in lambdas, and pass scopes and options to createStandaloneAppStartTransaction, whose callers already check them. - Compute the device family once instead of through a LazyEvaluator, whose evaluator must not return null. - Create the system events HandlerThread in the branch that uses it, inside the existing try. Co-Authored-By: Claude Opus 5.5 --- .../core/ActivityLifecycleIntegration.java | 12 +++++++----- .../java/io/sentry/android/core/AppState.java | 4 ++-- .../core/DefaultAndroidEventProcessor.java | 8 +++----- .../android/core/FeedbackShakeIntegration.java | 1 + .../SystemEventsBreadcrumbsIntegration.java | 17 +++++++++-------- .../core/ViewHierarchyEventProcessor.java | 2 +- .../android/core/anr/AnrProfileManager.java | 2 +- .../AndroidViewGestureTargetLocator.java | 2 +- .../internal/threaddump/ThreadDumpParser.java | 2 +- .../internal/tombstone/TombstoneParser.java | 1 + .../util/AndroidConnectionStatusProvider.java | 10 +++++----- .../core/AndroidLoggerBatchProcessorTest.kt | 4 ++-- .../core/AndroidMetricsBatchProcessorTest.kt | 4 ++-- .../core/SessionTrackingIntegrationTest.kt | 2 +- .../SystemEventsBreadcrumbsIntegrationTest.kt | 10 +++++----- .../core/anr/AnrProfilingIntegrationTest.kt | 6 +++--- .../util/AndroidConnectionStatusProviderTest.kt | 2 +- .../io/sentry/internal/gestures/UiElement.java | 2 +- .../io/sentry/protocol/ViewHierarchyNode.java | 2 +- 19 files changed, 48 insertions(+), 45 deletions(-) diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java b/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java index 4ab9be82248..324a726aada 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java @@ -176,7 +176,7 @@ private void stopPreviousTransactions() { } private void startTracing(final @NotNull Activity activity) { - if (scopes != null && !isRunningTransactionOrTrace(activity)) { + if (scopes != null && options != null && !isRunningTransactionOrTrace(activity)) { if (!performanceEnabled) { activitiesWithOngoingTransactions.put(activity, NoOpTransaction.getInstance()); if (options.isEnableAutoTraceIdGeneration()) { @@ -282,7 +282,7 @@ private void startTracing(final @NotNull Activity activity) { // Continue either the foreground app.start above or an earlier headless app.start. final @Nullable String continueSentryTrace; final @Nullable String continueBaggage; - if (createStandaloneAppStart) { + if (createStandaloneAppStart && appStartTransaction != null) { continueSentryTrace = appStartTransaction.toSentryTrace().getValue(); final @Nullable BaggageHeader baggageHeader = appStartTransaction.toBaggageHeader(null); continueBaggage = baggageHeader == null ? null : baggageHeader.getValue(); @@ -332,7 +332,7 @@ private void startTracing(final @NotNull Activity activity) { final SpanOptions spanOptions = new SpanOptions(); setSpanOrigin(spanOptions); - if (isAppStart) { + if (isAppStart && coldStart != null) { if (!createStandaloneAppStart && !options.isEnableStandaloneAppStartTracing()) { appStartSpan = transaction.startChild( @@ -980,7 +980,7 @@ private void onHeadlessAppStart() { } final @NotNull ITransaction transaction = - createStandaloneAppStartTransaction(startTime, null, false); + createStandaloneAppStartTransaction(scopes, options, startTime, null, false); transaction.finish(SpanStatus.OK, endTime); } @@ -991,6 +991,8 @@ private void onHeadlessAppStart() { * for its children and gets a deadline so it stays open until the extended span finishes. */ private @NotNull ITransaction createStandaloneAppStartTransaction( + final @NotNull IScopes scopes, + final @NotNull SentryAndroidOptions options, final @NotNull SentryDate startTime, final @Nullable TracesSamplingDecision samplingDecision, final boolean holdOpenForExtension) { @@ -1069,7 +1071,7 @@ private void onHeadlessAppStart() { metrics.setAppStartSamplingDecision(null); final @NotNull ITransaction transaction = - createStandaloneAppStartTransaction(startTime, samplingDecision, true); + createStandaloneAppStartTransaction(scopes, options, startTime, samplingDecision, true); final SpanOptions spanOptions = new SpanOptions(); setSpanOrigin(spanOptions); diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/AppState.java b/sentry-android-core/src/main/java/io/sentry/android/core/AppState.java index 74522f7aaac..24562e3aa49 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/AppState.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/AppState.java @@ -25,7 +25,7 @@ public final class AppState implements Closeable { private static @NotNull AppState instance = new AppState(); private final @NotNull AutoClosableReentrantLock lock = new AutoClosableReentrantLock(); - private volatile LifecycleObserver lifecycleObserver; + private volatile @Nullable LifecycleObserver lifecycleObserver; private MainLooperHandler handler = new MainLooperHandler(); private AppState() {} @@ -49,7 +49,7 @@ public void resetInstance() { @ApiStatus.Internal @TestOnly - public LifecycleObserver getLifecycleObserver() { + public @Nullable LifecycleObserver getLifecycleObserver() { return lifecycleObserver; } diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java b/sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java index b6fb245c11d..382c636dbdd 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java @@ -18,7 +18,6 @@ import io.sentry.protocol.SentryTransaction; import io.sentry.protocol.User; import io.sentry.util.HintUtils; -import io.sentry.util.LazyEvaluator; import io.sentry.util.Objects; import java.util.Collections; import java.util.List; @@ -40,8 +39,7 @@ final class DefaultAndroidEventProcessor implements SentryEventProcessor { private final @NotNull BuildInfoProvider buildInfoProvider; private final @NotNull SentryAndroidOptions options; @TestOnly final @Nullable Future deviceInfoUtil; - private final @NotNull LazyEvaluator deviceFamily = - new LazyEvaluator<>(() -> ContextUtils.getFamily(NoOpLogger.getInstance())); + private final @Nullable String deviceFamily = ContextUtils.getFamily(NoOpLogger.getInstance()); public DefaultAndroidEventProcessor( final @NotNull Context context, @@ -241,7 +239,7 @@ private void setDevice(final @NotNull SentryLogEvent event) { new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.MODEL)); event.setAttribute( "device.family", - new SentryLogEventAttributeValue(SentryAttributeType.STRING, deviceFamily.getValue())); + new SentryLogEventAttributeValue(SentryAttributeType.STRING, deviceFamily)); } catch (Throwable e) { options.getLogger().log(SentryLevel.ERROR, "Failed to retrieve device info", e); } @@ -269,7 +267,7 @@ private void setDevice(final @NotNull SentryMetricsEvent event) { new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.MODEL)); event.setAttribute( "device.family", - new SentryLogEventAttributeValue(SentryAttributeType.STRING, deviceFamily.getValue())); + new SentryLogEventAttributeValue(SentryAttributeType.STRING, deviceFamily)); } catch (Throwable e) { options.getLogger().log(SentryLevel.ERROR, "Failed to retrieve device info", e); } diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/FeedbackShakeIntegration.java b/sentry-android-core/src/main/java/io/sentry/android/core/FeedbackShakeIntegration.java index 4405cd19309..d8bf33b23da 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/FeedbackShakeIntegration.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/FeedbackShakeIntegration.java @@ -274,6 +274,7 @@ private void startShakeDetection(final @NotNull Activity activity) { final @Nullable WeakReference ref = currentActivityRef; final Activity active = ref != null ? ref.get() : null; final Boolean inBackground = AppState.getInstance().isInBackground(); + final @Nullable SentryAndroidOptions options = this.options; if (active == null || options == null || !enabled diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegration.java b/sentry-android-core/src/main/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegration.java index 3f45a9a9fb8..bdadeb0933f 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegration.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegration.java @@ -66,8 +66,8 @@ public final class SystemEventsBreadcrumbsIntegration private final @NotNull String[] actions; private volatile boolean isClosed = false; private volatile boolean isStopped = false; - private volatile IntentFilter filter = null; - private volatile HandlerThread handlerThread = null; + private volatile @Nullable IntentFilter filter = null; + private volatile @Nullable HandlerThread handlerThread = null; private final @NotNull AtomicBoolean isReceiverRegistered = new AtomicBoolean(false); private final @NotNull AutoClosableReentrantLock receiverLock = new AutoClosableReentrantLock(); // Track previous battery state to avoid duplicate breadcrumbs when values haven't changed @@ -152,12 +152,6 @@ private void registerReceiver( filter.addAction(item); } } - if (customHandler == null && handlerThread == null) { - handlerThread = - new HandlerThread( - "SystemEventsReceiver", Process.THREAD_PRIORITY_BACKGROUND); - handlerThread.start(); - } try { // registerReceiver can throw SecurityException but it's not documented in the // official docs @@ -167,6 +161,12 @@ private void registerReceiver( if (customHandler != null) { handler = customHandler; } else { + if (handlerThread == null) { + handlerThread = + new HandlerThread( + "SystemEventsReceiver", Process.THREAD_PRIORITY_BACKGROUND); + handlerThread.start(); + } handler = new Handler(handlerThread.getLooper()); } ContextUtils.registerReceiver(context, options, receiver, filter, handler); @@ -198,6 +198,7 @@ private void registerReceiver( @SuppressWarnings("Convert2MethodRef") // older AGP versions do not support method references private void scheduleUnregisterReceiver() { + final @Nullable SentryAndroidOptions options = this.options; if (options == null) { return; } diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ViewHierarchyEventProcessor.java b/sentry-android-core/src/main/java/io/sentry/android/core/ViewHierarchyEventProcessor.java index ffd3323e601..590afa3e556 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/ViewHierarchyEventProcessor.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/ViewHierarchyEventProcessor.java @@ -125,7 +125,7 @@ public ViewHierarchyEventProcessor(final @NotNull SentryAndroidOptions options) return event; } - public static byte[] snapshotViewHierarchyAsData( + public static @Nullable byte[] snapshotViewHierarchyAsData( @Nullable Activity activity, @NotNull IThreadChecker threadChecker, @NotNull ISerializer serializer, diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/anr/AnrProfileManager.java b/sentry-android-core/src/main/java/io/sentry/android/core/anr/AnrProfileManager.java index 7e3e1fd514e..06748574919 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/anr/AnrProfileManager.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/anr/AnrProfileManager.java @@ -61,7 +61,7 @@ public AnrProfileManager(final @NotNull SentryOptions options, final @NotNull Fi queueFile, new ObjectQueue.Converter() { @Override - public AnrStackTrace from(final byte[] source) throws IOException { + public @Nullable AnrStackTrace from(final byte[] source) throws IOException { // no need to close the streams since they are backed by byte arrays and don't // hold any resources final @NotNull ByteArrayInputStream bis = new ByteArrayInputStream(source); diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/AndroidViewGestureTargetLocator.java b/sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/AndroidViewGestureTargetLocator.java index 5f6187cd39a..5799f262ecb 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/AndroidViewGestureTargetLocator.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/AndroidViewGestureTargetLocator.java @@ -40,7 +40,7 @@ && isViewScrollable(view, isAndroidXAvailable.getValue())) { return null; } - private UiElement createUiElement(final @NotNull View targetView) { + private @Nullable UiElement createUiElement(final @NotNull View targetView) { final @Nullable String resourceName = ViewUtils.getResourceIdOrNull(targetView); if (resourceName == null) { return null; diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/internal/threaddump/ThreadDumpParser.java b/sentry-android-core/src/main/java/io/sentry/android/core/internal/threaddump/ThreadDumpParser.java index bfb829ce1a9..3408a5a79f5 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/internal/threaddump/ThreadDumpParser.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/internal/threaddump/ThreadDumpParser.java @@ -178,7 +178,7 @@ public void parse(final @NotNull Lines lines) { markThreads(); } - private SentryThread parseThread(final @NotNull Lines lines) { + private @Nullable SentryThread parseThread(final @NotNull Lines lines) { final SentryThread sentryThread = new SentryThread(); final Matcher beginManagedThreadRe = BEGIN_MANAGED_THREAD_RE.matcher(""); diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/internal/tombstone/TombstoneParser.java b/sentry-android-core/src/main/java/io/sentry/android/core/internal/tombstone/TombstoneParser.java index b6ac22b12ef..fdbddd3c3b5 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/internal/tombstone/TombstoneParser.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/internal/tombstone/TombstoneParser.java @@ -316,6 +316,7 @@ void extendTo(final @NotNull MemoryMapping mapping) { this.previousOffset = mapping.offset; } + @Nullable DebugImage toDebugImage() { if (buildId.isEmpty()) { return null; diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/internal/util/AndroidConnectionStatusProvider.java b/sentry-android-core/src/main/java/io/sentry/android/core/internal/util/AndroidConnectionStatusProvider.java index 62a212e6dcc..a2c17c5ee63 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/internal/util/AndroidConnectionStatusProvider.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/internal/util/AndroidConnectionStatusProvider.java @@ -311,16 +311,16 @@ private void updateCacheAndNotifyObservers( private boolean isSignificantChange(@Nullable NetworkCapabilities newCapabilities) { final NetworkCapabilities oldCapabilities = cachedNetworkCapabilities; - // Always significant if transitioning between null and non-null - if ((oldCapabilities == null) != (newCapabilities == null)) { - return true; - } - // If both null, no change if (oldCapabilities == null && newCapabilities == null) { return false; } + // Always significant if transitioning between null and non-null + if (oldCapabilities == null || newCapabilities == null) { + return true; + } + // Check significant capability changes if (hasSignificantCapabilityChanges(oldCapabilities, newCapabilities)) { return true; diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidLoggerBatchProcessorTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidLoggerBatchProcessorTest.kt index d9f9b1e3edd..3463daf1819 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidLoggerBatchProcessorTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidLoggerBatchProcessorTest.kt @@ -110,7 +110,7 @@ class AndroidLoggerBatchProcessorTest { val sut = fixture.getSut() sut.close(false) - assertTrue(AppState.getInstance().lifecycleObserver.listeners.isEmpty()) + assertTrue(AppState.getInstance().lifecycleObserver!!.listeners.isEmpty()) } @Test @@ -118,6 +118,6 @@ class AndroidLoggerBatchProcessorTest { val sut = fixture.getSut() sut.close(true) - assertTrue(AppState.getInstance().lifecycleObserver.listeners.isEmpty()) + assertTrue(AppState.getInstance().lifecycleObserver!!.listeners.isEmpty()) } } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidMetricsBatchProcessorTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidMetricsBatchProcessorTest.kt index 7648a2b3bab..a8309a03b94 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidMetricsBatchProcessorTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidMetricsBatchProcessorTest.kt @@ -109,7 +109,7 @@ class AndroidMetricsBatchProcessorTest { val sut = fixture.getSut() sut.close(false) - assertTrue(AppState.getInstance().lifecycleObserver.listeners.isEmpty()) + assertTrue(AppState.getInstance().lifecycleObserver!!.listeners.isEmpty()) } @Test @@ -117,6 +117,6 @@ class AndroidMetricsBatchProcessorTest { val sut = fixture.getSut() sut.close(true) - assertTrue(AppState.getInstance().lifecycleObserver.listeners.isEmpty()) + assertTrue(AppState.getInstance().lifecycleObserver!!.listeners.isEmpty()) } } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/SessionTrackingIntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/SessionTrackingIntegrationTest.kt index bbb8783d5fd..116f51af7ba 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/SessionTrackingIntegrationTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/SessionTrackingIntegrationTest.kt @@ -118,7 +118,7 @@ class SessionTrackingIntegrationTest { private fun setupLifecycle(): LifecycleRegistry { val lifecycle = LifecycleRegistry(ProcessLifecycleOwner.get()) - lifecycle.addObserver(AppState.getInstance().lifecycleObserver) + lifecycle.addObserver(AppState.getInstance().lifecycleObserver!!) return lifecycle } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegrationTest.kt index 2505b6f7f7d..60282aca26d 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegrationTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegrationTest.kt @@ -387,7 +387,7 @@ class SystemEventsBreadcrumbsIntegrationTest { sut.register(fixture.scopes, fixture.options) assertTrue( - AppState.getInstance().lifecycleObserver.listeners.any { + AppState.getInstance().lifecycleObserver!!.listeners.any { it is SystemEventsBreadcrumbsIntegration } ) @@ -401,7 +401,7 @@ class SystemEventsBreadcrumbsIntegrationTest { sut.register(fixture.scopes, fixture.options) assertFalse( - AppState.getInstance().lifecycleObserver.listeners.any { + AppState.getInstance().lifecycleObserver!!.listeners.any { it is SystemEventsBreadcrumbsIntegration } ) @@ -414,7 +414,7 @@ class SystemEventsBreadcrumbsIntegrationTest { sut.register(fixture.scopes, fixture.options) assertTrue( - AppState.getInstance().lifecycleObserver.listeners.any { + AppState.getInstance().lifecycleObserver!!.listeners.any { it is SystemEventsBreadcrumbsIntegration } ) @@ -422,7 +422,7 @@ class SystemEventsBreadcrumbsIntegrationTest { sut.close() assertFalse( - AppState.getInstance().lifecycleObserver.listeners.any { + AppState.getInstance().lifecycleObserver!!.listeners.any { it is SystemEventsBreadcrumbsIntegration } ) @@ -447,7 +447,7 @@ class SystemEventsBreadcrumbsIntegrationTest { shadowOf(Looper.getMainLooper()).idle() assertFalse( - AppState.getInstance().lifecycleObserver.listeners.any { + AppState.getInstance().lifecycleObserver!!.listeners.any { it is SystemEventsBreadcrumbsIntegration } ) diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/anr/AnrProfilingIntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/anr/AnrProfilingIntegrationTest.kt index 6d78a8f70c8..e11bca3c9de 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/anr/AnrProfilingIntegrationTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/anr/AnrProfilingIntegrationTest.kt @@ -94,7 +94,7 @@ class AnrProfilingIntegrationTest { val thread = integration.getProperty("thread") assertNotNull(thread) - assertTrue(AppState.getInstance().lifecycleObserver.listeners.isNotEmpty()) + assertTrue(AppState.getInstance().lifecycleObserver!!.listeners.isNotEmpty()) integration.close() thread.join(2000) @@ -102,7 +102,7 @@ class AnrProfilingIntegrationTest { assertTrue(!thread.isAlive) val enabled = integration.getProperty("enabled") assertTrue(!enabled.get()) - assertTrue(AppState.getInstance().lifecycleObserver.listeners.isEmpty()) + assertTrue(AppState.getInstance().lifecycleObserver!!.listeners.isEmpty()) } @Test @@ -334,7 +334,7 @@ class AnrProfilingIntegrationTest { val integration = AnrProfilingIntegration() integration.register(mockScopes, androidOptions) - assertFalse(AppState.getInstance().lifecycleObserver.listeners.isEmpty()) + assertFalse(AppState.getInstance().lifecycleObserver!!.listeners.isEmpty()) assertTrue(SentryIntegrationPackageStorage.getInstance().integrations.contains("AnrProfiling")) integration.close() diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/internal/util/AndroidConnectionStatusProviderTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/internal/util/AndroidConnectionStatusProviderTest.kt index 56a2a12928c..b8319d49e21 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/internal/util/AndroidConnectionStatusProviderTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/internal/util/AndroidConnectionStatusProviderTest.kt @@ -792,7 +792,7 @@ class AndroidConnectionStatusProviderTest { connectionStatusProvider.onBackground() assertFalse( - AppState.getInstance().lifecycleObserver.listeners.any { + AppState.getInstance().lifecycleObserver!!.listeners.any { it is SystemEventsBreadcrumbsIntegration } ) diff --git a/sentry/src/main/java/io/sentry/internal/gestures/UiElement.java b/sentry/src/main/java/io/sentry/internal/gestures/UiElement.java index c675910800a..92846cd8d96 100644 --- a/sentry/src/main/java/io/sentry/internal/gestures/UiElement.java +++ b/sentry/src/main/java/io/sentry/internal/gestures/UiElement.java @@ -51,7 +51,7 @@ public UiElement( } @Override - public boolean equals(Object o) { + public boolean equals(final @Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UiElement uiElement = (UiElement) o; diff --git a/sentry/src/main/java/io/sentry/protocol/ViewHierarchyNode.java b/sentry/src/main/java/io/sentry/protocol/ViewHierarchyNode.java index 525d644fdc5..97fbea385c0 100644 --- a/sentry/src/main/java/io/sentry/protocol/ViewHierarchyNode.java +++ b/sentry/src/main/java/io/sentry/protocol/ViewHierarchyNode.java @@ -49,7 +49,7 @@ public void setRenderingSystem(String renderingSystem) { this.renderingSystem = renderingSystem; } - public void setType(String type) { + public void setType(final @Nullable String type) { this.type = type; }