Skip to content

fix(feedback): Improve shake detection sensitivity#5366

Open
romtsn wants to merge 6 commits intomainfrom
rz/fix/shake-detection-sensitivity
Open

fix(feedback): Improve shake detection sensitivity#5366
romtsn wants to merge 6 commits intomainfrom
rz/fix/shake-detection-sensitivity

Conversation

@romtsn
Copy link
Copy Markdown
Member

@romtsn romtsn commented May 4, 2026

Replace the threshold-counting shake detection with a rolling sample window approach adapted from Square's Seismic library. The previous detector required 2 accelerometer spikes above 2.7g within 1.5s, which was too aggressive for many devices (e.g. HMD Global Pulse).

Detection algorithm

The new approach marks each accelerometer reading as "accelerating" if its magnitude exceeds 13 m/s² (~1.33g), then triggers a shake when >75% of samples in a 0.5s rolling window are accelerating. This catches moderate shakes reliably while still filtering out single bumps or drops. A SamplePool reuses Sample objects to avoid GC pressure from high-frequency sensor events.

Before, two individual high-g spikes within a time window:

if (gForceSquared > 2.7² && count >= 2 within 1.5s) → shake

After, sustained acceleration pattern over a sliding window:

if (>75% of samples in 0.5s exceed 13 m/s²) → shake

Stale form fields on re-show

When the per-form shake detection reuses the same SentryUserFeedbackForm instance, the message field now gets cleared in onStart() so subsequent shakes show a fresh form. Name and email are kept prefilled since they're typically the same user.

🤖 Generated with Claude Code

romtsn and others added 3 commits May 4, 2026 14:44
Replace the threshold-counting approach (2.7g, 2 spikes in 1.5s) with
a rolling sample window based on Square's Seismic library. A shake is
now detected when >75% of accelerometer readings in a 0.5s window
exceed 13 m/s² (~1.33g), which works reliably on budget devices with
less sensitive accelerometers.

Fixes GH-5331

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@sentry
Copy link
Copy Markdown

sentry Bot commented May 4, 2026

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.40.0 (1) release

⚙️ sentry-android Build Distribution Settings

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 317.90 ms 370.96 ms 53.06 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
8687935 294.00 ms 304.02 ms 10.02 ms
6edfca2 305.52 ms 432.78 ms 127.26 ms
b6702b0 395.86 ms 409.98 ms 14.12 ms
a1eadfa 345.67 ms 411.26 ms 65.59 ms
889ecea 367.58 ms 437.52 ms 69.94 ms
e2dce0b 315.85 ms 369.20 ms 53.35 ms
d15471f 322.58 ms 396.08 ms 73.50 ms
62b579c 349.26 ms 426.26 ms 77.00 ms
cf708bd 434.73 ms 502.96 ms 68.22 ms
6edfca2 316.43 ms 398.90 ms 82.46 ms

App size

Revision Plain With Sentry Diff
8687935 1.58 MiB 2.19 MiB 619.17 KiB
6edfca2 1.58 MiB 2.13 MiB 559.07 KiB
b6702b0 1.58 MiB 2.12 MiB 551.79 KiB
a1eadfa 0 B 0 B 0 B
889ecea 1.58 MiB 2.11 MiB 539.75 KiB
e2dce0b 0 B 0 B 0 B
d15471f 1.58 MiB 2.13 MiB 559.54 KiB
62b579c 0 B 0 B 0 B
cf708bd 1.58 MiB 2.11 MiB 539.71 KiB
6edfca2 1.58 MiB 2.13 MiB 559.07 KiB

Previous results on branch: rz/fix/shake-detection-sensitivity

Startup times

Revision Plain With Sentry Diff
19aaf3f 328.00 ms 360.78 ms 32.78 ms

App size

Revision Plain With Sentry Diff
19aaf3f 0 B 0 B 0 B

@romtsn romtsn marked this pull request as ready for review May 4, 2026 20:50
@romtsn romtsn requested review from adinauer and markushi as code owners May 4, 2026 20:50
@romtsn romtsn requested a review from antonis May 4, 2026 20:50
Comment on lines 91 to 97

public void stop() {
listener = null;
shakeCount = 0;
firstShakeTimestamp = 0;
queue.clear();
if (sensorManager != null) {
sensorManager.unregisterListener(this);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: A data race between stop() and onSensorChanged() can corrupt the SampleQueue's internal state, potentially causing an infinite loop that hangs a background thread.
Severity: HIGH

Suggested Fix

Synchronize all public methods of SampleQueue and SamplePool to ensure thread-safe access from both the main thread and the background sensor handler thread.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location:
sentry-android-core/src/main/java/io/sentry/android/core/SentryShakeDetector.java#L91-L97

Potential issue: A data race exists between the `stop()` method, called on the main
thread, and the `onSensorChanged()` method, called on a background `HandlerThread`. Both
methods concurrently access the unsynchronized `SampleQueue` and `SamplePool`.
Specifically, `stop()` calls `queue.clear()`, which releases `Sample` objects, while
`onSensorChanged()` calls `queue.add()`, which acquires them. This race on the shared
object pool can corrupt the underlying linked list, potentially creating a cycle. If a
cycle is created, the `clear()` method's loop will never terminate, causing the
`HandlerThread` to hang.

Did we get this right? 👍 / 👎 to inform future reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants