fix(feedback): Improve shake detection sensitivity#5366
Open
Conversation
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]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
📲 Install BuildsAndroid
|
Contributor
Performance metrics 🚀
|
| 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 |
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Comment on lines
91
to
97
|
|
||
| public void stop() { | ||
| listener = null; | ||
| shakeCount = 0; | ||
| firstShakeTimestamp = 0; | ||
| queue.clear(); | ||
| if (sensorManager != null) { | ||
| sensorManager.unregisterListener(this); | ||
| } |
There was a problem hiding this comment.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
SamplePoolreusesSampleobjects to avoid GC pressure from high-frequency sensor events.Before, two individual high-g spikes within a time window:
After, sustained acceleration pattern over a sliding window:
Stale form fields on re-show
When the per-form shake detection reuses the same
SentryUserFeedbackForminstance, the message field now gets cleared inonStart()so subsequent shakes show a fresh form. Name and email are kept prefilled since they're typically the same user.🤖 Generated with Claude Code