Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
2a0d6da
perf(connectivity): Cache network capabilities and status to reduce I…
romtsn Jul 16, 2025
0ac3081
Merge branch 'main' into rz/perf/less-ipc
romtsn Jul 16, 2025
14bb2d5
changelog
romtsn Jul 16, 2025
c82586d
Changelog
romtsn Jul 16, 2025
7418781
revert
romtsn Jul 16, 2025
f739d00
fix(breadcrumbs): Deduplicate battery breadcrumbs
romtsn Jul 16, 2025
833b026
ref
romtsn Jul 16, 2025
e4596ff
Changelog
romtsn Jul 16, 2025
0153ab5
Fix test
romtsn Jul 17, 2025
15794c6
Merge branch 'rz/perf/less-ipc' into rz/fix/diff-battery-crumbs
romtsn Jul 17, 2025
c31d648
perf(connectivity): Have only one NetworkCallback active at a time
romtsn Jul 18, 2025
83d80d7
Changelog
romtsn Jul 18, 2025
5b32662
perf(integrations): Use single lifecycle observer
romtsn Jul 23, 2025
5c5238a
Add tests
romtsn Jul 24, 2025
d2263b8
Changelog
romtsn Jul 24, 2025
42ff8e9
Fix tests
romtsn Jul 24, 2025
fde11a2
perf(integrations): Do not register for SystemEvents and NetworkCallb…
romtsn Jul 29, 2025
bba4efe
Do not cache importance
romtsn Jul 30, 2025
5edb0d3
Revert SR
romtsn Jul 30, 2025
d8402b6
Add tests
romtsn Jul 30, 2025
b7a5e0a
Spotless
romtsn Jul 30, 2025
c7cad14
Comment
romtsn Jul 30, 2025
8a6f145
Revert profiling
romtsn Jul 30, 2025
d868d1a
Changelog
romtsn Jul 30, 2025
c890fe3
fix test name
romtsn Jul 30, 2025
900ecb5
Update sentry-samples/sentry-samples-android/sdkperf/README.md
romtsn Jul 30, 2025
ac613d6
Update sentry-samples/sentry-samples-android/sdkperf/README.md
romtsn Jul 30, 2025
85f5bae
Update sentry-samples/sentry-samples-android/sdkperf/README.md
romtsn Jul 30, 2025
3f3a499
Update sentry-samples/sentry-samples-android/sdkperf/screen_flap.sh
romtsn Aug 1, 2025
c231dfc
Update sentry-samples/sentry-samples-android/sdkperf/wifi_flap.sh
romtsn Aug 1, 2025
cda0b1d
Address PR review
romtsn Aug 1, 2025
f7179a5
Formatting
romtsn Aug 1, 2025
d4e8b1f
Merge branch 'main' into rz/perf/no-network-on-background
romtsn Aug 5, 2025
c648064
Fix merge conflict
romtsn Aug 5, 2025
12a6347
Fix tests
romtsn Aug 5, 2025
4cbaa1c
Revert
romtsn Aug 6, 2025
38a7cbb
Merge branch 'main' into rz/perf/no-network-on-background
romtsn Aug 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- Deduplicate battery breadcrumbs ([#4561](https://github.com/getsentry/sentry-java/pull/4561))
- Remove unused method in ManifestMetadataReader ([#4585](https://github.com/getsentry/sentry-java/pull/4585))
- Have single `NetworkCallback` registered at a time to reduce IPC calls ([#4562](https://github.com/getsentry/sentry-java/pull/4562))
- Do not register for SystemEvents and NetworkCallbacks immediately when launched with non-foreground importance ([#4579](https://github.com/getsentry/sentry-java/pull/4579))
- Limit ProGuard keep rules for native methods within `sentry-android-ndk` to the `io.sentry.**` namespace. ([#4427](https://github.com/getsentry/sentry-java/pull/4427))
- If you relied on the Sentry SDK to keep native method names for JNI compatibility within your namespace, please review your ProGuard rules and ensure the configuration still works. Especially when you're not consuming any of the default Android proguard rules (`proguard-android.txt` or `proguard-android-optimize.txt`) the following config should be present:
```
Expand Down
13 changes: 13 additions & 0 deletions sentry-android-core/api/sentry-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -167,16 +167,29 @@ public final class io/sentry/android/core/AppLifecycleIntegration : io/sentry/In
}

public final class io/sentry/android/core/AppState : java/io/Closeable {
public fun addAppStateListener (Lio/sentry/android/core/AppState$AppStateListener;)V
public fun close ()V
public static fun getInstance ()Lio/sentry/android/core/AppState;
public fun getLifecycleObserver ()Lio/sentry/android/core/AppState$LifecycleObserver;
public fun isInBackground ()Ljava/lang/Boolean;
public fun registerLifecycleObserver (Lio/sentry/SentryOptions;)V
public fun removeAppStateListener (Lio/sentry/android/core/AppState$AppStateListener;)V
public fun resetInstance ()V
public fun unregisterLifecycleObserver ()V
}

public abstract interface class io/sentry/android/core/AppState$AppStateListener {
public abstract fun onBackground ()V
public abstract fun onForeground ()V
}

public final class io/sentry/android/core/AppState$LifecycleObserver : androidx/lifecycle/DefaultLifecycleObserver {
public fun <init> (Lio/sentry/android/core/AppState;)V
public fun getListeners ()Ljava/util/List;
public fun onStart (Landroidx/lifecycle/LifecycleOwner;)V
public fun onStop (Landroidx/lifecycle/LifecycleOwner;)V
}

public final class io/sentry/android/core/BuildConfig {
public static final field BUILD_TYPE Ljava/lang/String;
public static final field DEBUG Z
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import androidx.annotation.NonNull;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ProcessLifecycleOwner;
import io.sentry.ILogger;
import io.sentry.ISentryLifecycleToken;
import io.sentry.NoOpLogger;
import io.sentry.SentryLevel;
import io.sentry.SentryOptions;
import io.sentry.android.core.internal.util.AndroidThreadChecker;
import io.sentry.util.AutoClosableReentrantLock;
import java.io.Closeable;
Expand Down Expand Up @@ -36,21 +36,23 @@ private AppState() {}

private volatile @Nullable Boolean inBackground = null;

@TestOnly
LifecycleObserver getLifecycleObserver() {
return lifecycleObserver;
}

@TestOnly
void setHandler(final @NotNull MainLooperHandler handler) {
this.handler = handler;
}

@ApiStatus.Internal
@TestOnly
void resetInstance() {
public void resetInstance() {
instance = new AppState();
}

@ApiStatus.Internal
@TestOnly
public LifecycleObserver getLifecycleObserver() {
return lifecycleObserver;
}

public @Nullable Boolean isInBackground() {
return inBackground;
}
Expand All @@ -59,7 +61,7 @@ void setInBackground(final boolean inBackground) {
this.inBackground = inBackground;
}

void addAppStateListener(final @NotNull AppStateListener listener) {
public void addAppStateListener(final @NotNull AppStateListener listener) {
try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) {
ensureLifecycleObserver(NoOpLogger.getInstance());

Expand All @@ -69,15 +71,16 @@ void addAppStateListener(final @NotNull AppStateListener listener) {
}
}

void removeAppStateListener(final @NotNull AppStateListener listener) {
public void removeAppStateListener(final @NotNull AppStateListener listener) {
try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) {
if (lifecycleObserver != null) {
lifecycleObserver.listeners.remove(listener);
}
}
}

void registerLifecycleObserver(final @Nullable SentryAndroidOptions options) {
@ApiStatus.Internal
public void registerLifecycleObserver(final @Nullable SentryOptions options) {
if (lifecycleObserver != null) {
return;
}
Expand Down Expand Up @@ -133,7 +136,8 @@ private void addObserverInternal(final @NotNull ILogger logger) {
}
}

void unregisterLifecycleObserver() {
@ApiStatus.Internal
public void unregisterLifecycleObserver() {
if (lifecycleObserver == null) {
return;
}
Expand Down Expand Up @@ -167,7 +171,8 @@ public void close() throws IOException {
unregisterLifecycleObserver();
}

final class LifecycleObserver implements DefaultLifecycleObserver {
@ApiStatus.Internal
public final class LifecycleObserver implements DefaultLifecycleObserver {
final List<AppStateListener> listeners =
new CopyOnWriteArrayList<AppStateListener>() {
@Override
Expand All @@ -184,6 +189,12 @@ public boolean add(AppStateListener appStateListener) {
}
};

@ApiStatus.Internal
@TestOnly
public List<AppStateListener> getListeners() {
return listeners;
}

@Override
public void onStart(@NonNull LifecycleOwner owner) {
setInBackground(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import io.sentry.SentryOptions;
import io.sentry.android.core.util.AndroidLazyEvaluator;
import io.sentry.protocol.App;
import io.sentry.util.LazyEvaluator;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
Expand Down Expand Up @@ -91,20 +90,6 @@ private ContextUtils() {}
// to avoid doing a bunch of Binder calls we use LazyEvaluator to cache the values that are static
// during the app process running

private static final @NotNull LazyEvaluator<Boolean> isForegroundImportance =
new LazyEvaluator<>(
() -> {
try {
final ActivityManager.RunningAppProcessInfo appProcessInfo =
new ActivityManager.RunningAppProcessInfo();
ActivityManager.getMyMemoryState(appProcessInfo);
return appProcessInfo.importance == IMPORTANCE_FOREGROUND;
} catch (Throwable ignored) {
// should never happen
}
return false;
});

/**
* Since this packageInfo uses flags 0 we can assume it's static and cache it as the package name
* or version code cannot change during runtime, only after app update (which will spin up a new
Expand Down Expand Up @@ -284,7 +269,15 @@ static String getVersionName(final @NotNull PackageInfo packageInfo) {
*/
@ApiStatus.Internal
public static boolean isForegroundImportance() {
return isForegroundImportance.getValue();
try {
final ActivityManager.RunningAppProcessInfo appProcessInfo =
new ActivityManager.RunningAppProcessInfo();
ActivityManager.getMyMemoryState(appProcessInfo);
return appProcessInfo.importance == IMPORTANCE_FOREGROUND;
} catch (Throwable ignored) {
// should never happen
}
return false;
}

/**
Expand Down Expand Up @@ -544,7 +537,6 @@ public static Context getApplicationContext(final @NotNull Context context) {

@TestOnly
static void resetInstance() {
isForegroundImportance.resetValue();
staticPackageInfo33.resetValue();
staticPackageInfo.resetValue();
applicationName.resetValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
Expand All @@ -62,6 +63,7 @@ public final class SystemEventsBreadcrumbsIntegration
private volatile boolean isClosed = false;
private volatile boolean isStopped = false;
private volatile IntentFilter filter = 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
private @Nullable BatteryState previousBatteryState;
Expand Down Expand Up @@ -101,14 +103,15 @@ public void register(final @NotNull IScopes scopes, final @NotNull SentryOptions

if (this.options.isEnableSystemEventBreadcrumbs()) {
AppState.getInstance().addAppStateListener(this);
registerReceiver(this.scopes, this.options, /* reportAsNewIntegration= */ true);

if (ContextUtils.isForegroundImportance()) {
registerReceiver(this.scopes, this.options);
}
}
}

private void registerReceiver(
final @NotNull IScopes scopes,
final @NotNull SentryAndroidOptions options,
final boolean reportAsNewIntegration) {
final @NotNull IScopes scopes, final @NotNull SentryAndroidOptions options) {

if (!options.isEnableSystemEventBreadcrumbs()) {
return;
Expand Down Expand Up @@ -139,7 +142,7 @@ private void registerReceiver(
// registerReceiver can throw SecurityException but it's not documented in the
// official docs
ContextUtils.registerReceiver(context, options, receiver, filter);
if (reportAsNewIntegration) {
if (!isReceiverRegistered.getAndSet(true)) {
options
.getLogger()
.log(SentryLevel.DEBUG, "SystemEventsBreadcrumbsIntegration installed.");
Expand Down Expand Up @@ -239,7 +242,7 @@ public void onForeground() {

isStopped = false;

registerReceiver(scopes, options, /* reportAsNewIntegration= */ false);
registerReceiver(scopes, options);
}

@Override
Expand Down
Loading
Loading