Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -22,6 +22,7 @@

### Fixes

- Fix `NoSuchMethodError` when using `Math.floorDiv`/`Math.floorMod` on Android < 24 ([#5743](https://github.com/getsentry/sentry-java/pull/5743))
- Fix main thread identification parsing for ApplicationExitInfo ANRs ([#5733](https://github.com/getsentry/sentry-java/pull/5733))
- Do not send threads without stacktraces for ApplicationExitInfo ANRs ([#5733](https://github.com/getsentry/sentry-java/pull/5733))
- Record byte-level client reports when event processors discard logs or trace metrics ([#5718](https://github.com/getsentry/sentry-java/pull/5718))
Expand Down
28 changes: 28 additions & 0 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,34 @@ limitations under the License.

---

## Google Guava — LongMath (Apache 2.0)

**Source:** https://github.com/google/guava/blob/v33.0.0/guava/src/com/google/common/math/LongMath.java<br>
**License:** Apache License 2.0<br>
**Copyright:** Copyright (C) 2011 The Guava Authors

### Scope

The Sentry Java SDK includes adapted floor division logic from Guava's `LongMath` class to support older Android API levels. The code resides in `io.sentry.vendor.SentryMath`.

```
Copyright (C) 2011 The Guava Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```

---

## FasterXML Jackson — ISO8601Utils (Apache 2.0)

**Source:** https://github.com/FasterXML/jackson-databind<br>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ public static long parseTimestamp(final @NotNull String timestamp) {
return formatTimestampWithCalendar(millis);
}

final long epochDay = Math.floorDiv(millis, MILLIS_PER_DAY);
int millisOfDay = (int) Math.floorMod(millis, MILLIS_PER_DAY);
final long epochDay = SentryMath.floorDiv(millis, MILLIS_PER_DAY);
int millisOfDay = (int) SentryMath.floorMod(millis, MILLIS_PER_DAY);

final int[] yearMonthDay = epochDayToYearMonthDay(epochDay);
final int hour = millisOfDay / (int) MILLIS_PER_HOUR;
Expand Down Expand Up @@ -281,7 +281,7 @@ private static long epochMillis(

private static long daysFromYearMonthDay(int year, final int month, final int day) {
year -= month <= 2 ? 1 : 0;
final long era = Math.floorDiv(year, 400);
final long era = SentryMath.floorDiv(year, 400L);
final int yearOfEra = (int) (year - era * 400);
final int dayOfYear = (153 * (month + (month > 2 ? -3 : 9)) + 2) / 5 + day - 1;
final int dayOfEra = yearOfEra * 365 + yearOfEra / 4 - yearOfEra / 100 + dayOfYear;
Expand All @@ -290,7 +290,7 @@ private static long daysFromYearMonthDay(int year, final int month, final int da

private static int[] epochDayToYearMonthDay(long epochDay) {
epochDay += DAYS_0000_TO_1970;
final long era = Math.floorDiv(epochDay, 146097);
final long era = SentryMath.floorDiv(epochDay, 146097L);
final int dayOfEra = (int) (epochDay - era * 146097);
final int yearOfEra = (dayOfEra - dayOfEra / 1460 + dayOfEra / 36524 - dayOfEra / 146096) / 365;
final int year = (int) (yearOfEra + era * 400);
Expand Down
40 changes: 40 additions & 0 deletions sentry/src/main/java/io/sentry/vendor/SentryMath.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Adapted from https://github.com/google/guava/blob/v33.0.0/guava/src/com/google/common/math/LongMath.java
*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.sentry.vendor;

final class SentryMath {

private SentryMath() {}

static long floorDiv(final long x, final long y) {
final long quotient = x / y;
final long remainder = x - y * quotient;

if (remainder == 0) {
return quotient;
}

final int signum = 1 | (int) ((x ^ y) >> (Long.SIZE - 1));
return signum < 0 ? quotient + signum : quotient;
Comment thread
cursor[bot] marked this conversation as resolved.
}

static long floorMod(final long x, final long y) {
return x - floorDiv(x, y) * y;
}
}
58 changes: 58 additions & 0 deletions sentry/src/test/java/io/sentry/vendor/SentryMathTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.sentry.vendor

import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlin.test.assertFailsWith

class SentryMathTest {
@Test
fun `floorDiv matches Java Math floorDiv`() {
values.forEach { x ->
divisors.forEach { y -> assertThat(SentryMath.floorDiv(x, y)).isEqualTo(Math.floorDiv(x, y)) }
}
}

@Test
fun `floorMod matches Java Math floorMod`() {
values.forEach { x ->
divisors.forEach { y -> assertThat(SentryMath.floorMod(x, y)).isEqualTo(Math.floorMod(x, y)) }
}
}

@Test
fun `floorDiv throws when dividing by zero`() {
assertFailsWith<ArithmeticException> { SentryMath.floorDiv(1L, 0L) }
}

@Test
fun `floorMod throws when dividing by zero`() {
assertFailsWith<ArithmeticException> { SentryMath.floorMod(1L, 0L) }
}

private companion object {
val values =
listOf(
Long.MIN_VALUE,
-86_400_001L,
-86_400_000L,
-86_399_999L,
-401L,
-400L,
-399L,
-2L,
-1L,
0L,
1L,
2L,
399L,
400L,
401L,
86_399_999L,
86_400_000L,
86_400_001L,
Long.MAX_VALUE,
)

val divisors = listOf(Long.MIN_VALUE, -146_097L, -400L, -1L, 1L, 400L, 146_097L, Long.MAX_VALUE)
}
}
Loading