Skip to content

Commit c208299

Browse files
authored
Merge branch 'main' into fix/ci/remove-obsolete-ndk-symbols
2 parents 137669a + 15535b8 commit c208299

File tree

16 files changed

+1210
-313
lines changed

16 files changed

+1210
-313
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Improvements
6+
7+
- Session Replay: Use main thread looper to schedule replay capture ([#4542](https://github.com/getsentry/sentry-java/pull/4542))
8+
9+
### Fixes
10+
11+
- Cache network capabilities and status to reduce IPC calls ([#4560](https://github.com/getsentry/sentry-java/pull/4560))
12+
- Deduplicate battery breadcrumbs ([#4561](https://github.com/getsentry/sentry-java/pull/4561))
13+
14+
315
## 8.18.0
416

517
### Features

sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import io.sentry.android.core.internal.gestures.AndroidViewGestureTargetLocator;
2929
import io.sentry.android.core.internal.modules.AssetsModulesLoader;
3030
import io.sentry.android.core.internal.util.AndroidConnectionStatusProvider;
31+
import io.sentry.android.core.internal.util.AndroidCurrentDateProvider;
3132
import io.sentry.android.core.internal.util.AndroidThreadChecker;
3233
import io.sentry.android.core.internal.util.SentryFrameMetricsCollector;
3334
import io.sentry.android.core.performance.AppStartMetrics;
@@ -157,7 +158,8 @@ static void initializeIntegrationsAndProcessors(
157158

158159
if (options.getConnectionStatusProvider() instanceof NoOpConnectionStatusProvider) {
159160
options.setConnectionStatusProvider(
160-
new AndroidConnectionStatusProvider(context, options.getLogger(), buildInfoProvider));
161+
new AndroidConnectionStatusProvider(
162+
context, options, buildInfoProvider, AndroidCurrentDateProvider.getInstance()));
161163
}
162164

163165
if (options.getCacheDirPath() != null) {

sentry-android-core/src/main/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegration.java

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ public final class SystemEventsBreadcrumbsIntegration implements Integration, Cl
7171
private volatile boolean isStopped = false;
7272
private volatile IntentFilter filter = null;
7373
private final @NotNull AutoClosableReentrantLock receiverLock = new AutoClosableReentrantLock();
74+
// Track previous battery state to avoid duplicate breadcrumbs when values haven't changed
75+
private @Nullable BatteryState previousBatteryState;
7476

7577
public SystemEventsBreadcrumbsIntegration(final @NotNull Context context) {
7678
this(context, getDefaultActionsInternal());
@@ -331,7 +333,7 @@ public void onStop(@NonNull LifecycleOwner owner) {
331333
}
332334
}
333335

334-
static final class SystemEventsBroadcastReceiver extends BroadcastReceiver {
336+
final class SystemEventsBroadcastReceiver extends BroadcastReceiver {
335337

336338
private static final long DEBOUNCE_WAIT_TIME_MS = 60 * 1000;
337339
private final @NotNull IScopes scopes;
@@ -350,19 +352,36 @@ public void onReceive(final Context context, final @NotNull Intent intent) {
350352
final @Nullable String action = intent.getAction();
351353
final boolean isBatteryChanged = ACTION_BATTERY_CHANGED.equals(action);
352354

353-
// aligning with iOS which only captures battery status changes every minute at maximum
354-
if (isBatteryChanged && batteryChangedDebouncer.checkForDebounce()) {
355-
return;
355+
@Nullable BatteryState batteryState = null;
356+
if (isBatteryChanged) {
357+
if (batteryChangedDebouncer.checkForDebounce()) {
358+
// aligning with iOS which only captures battery status changes every minute at maximum
359+
return;
360+
}
361+
362+
// For battery changes, check if the actual values have changed
363+
final @Nullable Float batteryLevel = DeviceInfoUtil.getBatteryLevel(intent, options);
364+
final @Nullable Integer currentBatteryLevel =
365+
batteryLevel != null ? batteryLevel.intValue() : null;
366+
final @Nullable Boolean currentChargingState = DeviceInfoUtil.isCharging(intent, options);
367+
batteryState = new BatteryState(currentBatteryLevel, currentChargingState);
368+
369+
// Only create breadcrumb if battery state has actually changed
370+
if (batteryState.equals(previousBatteryState)) {
371+
return;
372+
}
373+
374+
previousBatteryState = batteryState;
356375
}
357376

377+
final BatteryState state = batteryState;
358378
final long now = System.currentTimeMillis();
359379
try {
360380
options
361381
.getExecutorService()
362382
.submit(
363383
() -> {
364-
final Breadcrumb breadcrumb =
365-
createBreadcrumb(now, intent, action, isBatteryChanged);
384+
final Breadcrumb breadcrumb = createBreadcrumb(now, intent, action, state);
366385
final Hint hint = new Hint();
367386
hint.set(ANDROID_INTENT, intent);
368387
scopes.addBreadcrumb(breadcrumb, hint);
@@ -411,7 +430,7 @@ String getStringAfterDotFast(final @Nullable String str) {
411430
final long timeMs,
412431
final @NotNull Intent intent,
413432
final @Nullable String action,
414-
boolean isBatteryChanged) {
433+
final @Nullable BatteryState batteryState) {
415434
final Breadcrumb breadcrumb = new Breadcrumb(timeMs);
416435
breadcrumb.setType("system");
417436
breadcrumb.setCategory("device.event");
@@ -420,14 +439,12 @@ String getStringAfterDotFast(final @Nullable String str) {
420439
breadcrumb.setData("action", shortAction);
421440
}
422441

423-
if (isBatteryChanged) {
424-
final Float batteryLevel = DeviceInfoUtil.getBatteryLevel(intent, options);
425-
if (batteryLevel != null) {
426-
breadcrumb.setData("level", batteryLevel);
442+
if (batteryState != null) {
443+
if (batteryState.level != null) {
444+
breadcrumb.setData("level", batteryState.level);
427445
}
428-
final Boolean isCharging = DeviceInfoUtil.isCharging(intent, options);
429-
if (isCharging != null) {
430-
breadcrumb.setData("charging", isCharging);
446+
if (batteryState.charging != null) {
447+
breadcrumb.setData("charging", batteryState.charging);
431448
}
432449
} else {
433450
final Bundle extras = intent.getExtras();
@@ -458,4 +475,26 @@ String getStringAfterDotFast(final @Nullable String str) {
458475
return breadcrumb;
459476
}
460477
}
478+
479+
static final class BatteryState {
480+
private final @Nullable Integer level;
481+
private final @Nullable Boolean charging;
482+
483+
BatteryState(final @Nullable Integer level, final @Nullable Boolean charging) {
484+
this.level = level;
485+
this.charging = charging;
486+
}
487+
488+
@Override
489+
public boolean equals(final @Nullable Object other) {
490+
if (!(other instanceof BatteryState)) return false;
491+
BatteryState that = (BatteryState) other;
492+
return Objects.equals(level, that.level) && Objects.equals(charging, that.charging);
493+
}
494+
495+
@Override
496+
public int hashCode() {
497+
return Objects.hash(level, charging);
498+
}
499+
}
461500
}

0 commit comments

Comments
 (0)