diff --git a/CHANGELOG.md b/CHANGELOG.md
index d6a3b55b40..22a9a8eefa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## Unreleased
+
+### Features
+
+- Add opt-in binder (IPC) tracing and logging instrumentation for Android ([#5515](https://github.com/getsentry/sentry-java/pull/5515))
+ - Enable spans via `options.isEnableBinderTracing = true` or manifest: ``
+ - Enable logs via `options.isEnableBinderLogging = true` or manifest: ``
+
## 8.43.1
### Fixes
diff --git a/sentry-android-core/api/sentry-android-core.api b/sentry-android-core/api/sentry-android-core.api
index 249549f836..846635db04 100644
--- a/sentry-android-core/api/sentry-android-core.api
+++ b/sentry-android-core/api/sentry-android-core.api
@@ -386,6 +386,8 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
public fun isEnableAppLifecycleBreadcrumbs ()Z
public fun isEnableAutoActivityLifecycleTracing ()Z
public fun isEnableAutoTraceIdGeneration ()Z
+ public fun isEnableBinderLogging ()Z
+ public fun isEnableBinderTracing ()Z
public fun isEnableFramesTracking ()Z
public fun isEnableNdk ()Z
public fun isEnableNetworkEventBreadcrumbs ()Z
@@ -417,6 +419,8 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
public fun setEnableAppLifecycleBreadcrumbs (Z)V
public fun setEnableAutoActivityLifecycleTracing (Z)V
public fun setEnableAutoTraceIdGeneration (Z)V
+ public fun setEnableBinderLogging (Z)V
+ public fun setEnableBinderTracing (Z)V
public fun setEnableFramesTracking (Z)V
public fun setEnableNdk (Z)V
public fun setEnableNetworkEventBreadcrumbs (Z)V
diff --git a/sentry-android-core/proguard-rules.pro b/sentry-android-core/proguard-rules.pro
index 4cd76f9a20..40187f1f6c 100644
--- a/sentry-android-core/proguard-rules.pro
+++ b/sentry-android-core/proguard-rules.pro
@@ -92,3 +92,5 @@
-dontwarn io.sentry.spotlight.SpotlightIntegration
-keepnames class io.sentry.spotlight.SpotlightIntegration
##---------------End: proguard configuration for sentry-spotlight ----------
+
+-keepnames class io.sentry.android.core.internal.binder.SentryBinderAdapter { *; }
diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java b/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java
index e16d4b312f..5ecd201159 100644
--- a/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java
+++ b/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java
@@ -188,6 +188,10 @@ final class ManifestMetadataReader {
static final String ENABLE_ANR_FINGERPRINTING = "io.sentry.anr.enable-fingerprinting";
+ static final String ENABLE_BINDER_TRACING = "io.sentry.traces.binder.enable";
+
+ static final String ENABLE_BINDER_LOGGING = "io.sentry.logs.binder.enable";
+
/** ManifestMetadataReader ctor */
private ManifestMetadataReader() {}
@@ -725,6 +729,12 @@ static void applyMetadata(
options.setEnableAnrFingerprinting(
readBool(
metadata, logger, ENABLE_ANR_FINGERPRINTING, options.isEnableAnrFingerprinting()));
+
+ options.setEnableBinderTracing(
+ readBool(metadata, logger, ENABLE_BINDER_TRACING, options.isEnableBinderTracing()));
+
+ options.setEnableBinderLogging(
+ readBool(metadata, logger, ENABLE_BINDER_LOGGING, options.isEnableBinderLogging()));
}
options
.getLogger()
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 0d249f7379..ddb77ef979 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
@@ -14,6 +14,7 @@
import io.sentry.SentryLevel;
import io.sentry.SentryOptions;
import io.sentry.Session;
+import io.sentry.android.core.internal.binder.SentryBinderAdapter;
import io.sentry.android.core.performance.AppStartMetrics;
import io.sentry.android.core.performance.TimeSpan;
import io.sentry.android.fragment.FragmentLifecycleIntegration;
@@ -151,6 +152,9 @@ public static void init(
t);
}
+ SentryBinderAdapter.setEnabled(
+ options.isEnableBinderTracing(), options.isEnableBinderLogging());
+
// if SentryPerformanceProvider was disabled or removed,
// we set the app start / sdk init time here instead
final @NotNull AppStartMetrics appStartMetrics = AppStartMetrics.getInstance();
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 bb9ec17aab..9655edd99b 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
@@ -263,6 +263,12 @@ public interface BeforeCaptureCallback {
private boolean enableAnrFingerprinting = true;
+ /** Enable or disable creating spans for binder (IPC) calls. Default is disabled. */
+ private boolean enableBinderTracing = false;
+
+ /** Enable or disable logging of binder (IPC) calls. Default is disabled. */
+ private boolean enableBinderLogging = false;
+
public SentryAndroidOptions() {
setSentryClientName(BuildConfig.SENTRY_ANDROID_SDK_NAME + "/" + BuildConfig.VERSION_NAME);
setSdkVersion(createSdkVersion());
@@ -755,6 +761,42 @@ public void setEnableAnrFingerprinting(final boolean enableAnrFingerprinting) {
this.enableAnrFingerprinting = enableAnrFingerprinting;
}
+ /**
+ * Returns whether creating spans for binder (IPC) calls is enabled. Default is disabled.
+ *
+ * @return true if binder spans are enabled
+ */
+ public boolean isEnableBinderTracing() {
+ return enableBinderTracing;
+ }
+
+ /**
+ * Enables or disables creating spans for binder (IPC) calls.
+ *
+ * @param enableBinderTracing true to enable binder spans
+ */
+ public void setEnableBinderTracing(final boolean enableBinderTracing) {
+ this.enableBinderTracing = enableBinderTracing;
+ }
+
+ /**
+ * Returns whether logging of binder (IPC) calls is enabled. Default is disabled.
+ *
+ * @return true if binder logging is enabled
+ */
+ public boolean isEnableBinderLogging() {
+ return enableBinderLogging;
+ }
+
+ /**
+ * Enables or disables logging of binder (IPC) calls.
+ *
+ * @param enableBinderLogging true to enable binder logging
+ */
+ public void setEnableBinderLogging(final boolean enableBinderLogging) {
+ this.enableBinderLogging = enableBinderLogging;
+ }
+
static class AndroidUserFeedbackFormHandler implements SentryFeedbackOptions.IFormHandler {
@Override
public void showForm(
diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/internal/binder/SentryBinderAdapter.java b/sentry-android-core/src/main/java/io/sentry/android/core/internal/binder/SentryBinderAdapter.java
new file mode 100644
index 0000000000..bf04a5b4d0
--- /dev/null
+++ b/sentry-android-core/src/main/java/io/sentry/android/core/internal/binder/SentryBinderAdapter.java
@@ -0,0 +1,126 @@
+package io.sentry.android.core.internal.binder;
+
+import android.os.Build;
+import io.sentry.ISpan;
+import io.sentry.Sentry;
+import io.sentry.SentryAttributes;
+import io.sentry.SentryLogLevel;
+import io.sentry.SpanDataConvention;
+import io.sentry.logger.SentryLogParameters;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+@SuppressWarnings({"unused", "deprecation"})
+@ApiStatus.Internal
+public final class SentryBinderAdapter {
+
+ private static final AtomicInteger cookieCounter = new AtomicInteger();
+ private static final int NO_COOKIE = -1;
+
+ private static volatile boolean tracingEnabled = false;
+ private static volatile boolean loggingEnabled = false;
+
+ /** Configures which binder features are active. Expected to be called once during SDK init. */
+ public static void setEnabled(final boolean tracingEnabled, final boolean loggingEnabled) {
+ SentryBinderAdapter.tracingEnabled = tracingEnabled;
+ SentryBinderAdapter.loggingEnabled = loggingEnabled;
+ }
+
+ private static final ThreadLocal