Skip to content

Fix redaction running debug apps out of memory; opt-in field masking; one-finger edge swipe - #28

Merged
abhishek-3289 merged 1 commit into
mainfrom
fix-redaction-memory
Nov 10, 2026
Merged

abhishek-3289 merged 1 commit into
mainfrom
fix-redaction-memory

Conversation

@abhishek-3289

Copy link
Copy Markdown
Collaborator

Why

A StockX debug build aborted in NetworkRedaction.body (JNI DETECTED ERROR → Runtime aborting) while DevDeck's OkHttp interceptor masked a GraphQL response.

Kotlin's Regex.replace calls matcher.pattern().matcher(input) for every match (MatcherMatchResult.next, kotlin-stdlib 2.2.21). On Android each new Matcher copies the whole input into native memory through ICU, so a 240K-character body with thousands of JSON strings made thousands of ~500 KB copies. When ICU's allocation failed it raised OutOfMemoryError and then called FindClass with that exception pending, which CheckJNI (on in debug builds) turns into an abort.

What

Redaction

  • NetworkRedaction uses one java.util.regex.Matcher per body, and skips the regex entirely when a body contains none of the field names (URL-encoded bodies still get the full pass).
  • NetworkLogger.complete masks once, before the StateFlow update, instead of inside its retry lambda.
  • Field masking is now opt-in: NetworkLogger.redactedFields is empty by default. Auth, cookie, API-key and CSRF headers are still masked. NetworkLogger.DEFAULT_REDACTED_FIELDS turns field masking back on.

One-finger edge swipe

  • DeckGestures(oneFingerSwipe = true): one finger swiping in from the drawer's edge (within 24dp) opens it. Off by default; the two-finger swipe is unchanged and each can be turned on or off.
  • While the drawer is closed and the option is on, a 200dp strip in the middle of that edge is excluded from the system back gesture so the swipe reaches the app.
  • The sample has a One-finger swipe from the edge switch.

Compatibility

The old DeckGestures constructor and copy are kept as hidden overloads. Changing the masking default is a behaviour change, noted in the CHANGELOG.

Checks

  • ktlintCheck lintDebug lintRelease assembleRelease testDebugUnitTest apiCheck :sample:assembleQa pass locally.

  • New tests: a 240K-character body with thousands of secrets, untouched bodies without secret names, URL-encoded field names, and the edge swipe tracker (both sides, start away from the edge, vertical drags, second finger, wrong direction).

  • Emulator stress test (temporary button, not committed; 4 threads × 5 bodies of 240K characters):

    Before After
    Time per body 7.1 s 27–124 ms
    Peak native heap 703 MB, then killed (LOW_MEMORY) 21.6 MB
    Bodies finished 1 of 20 20 of 20
  • Emulator: with the one-finger option on, a swipe in from the middle of the right edge opened the drawer and a swipe starting mid-screen didn't; with it off, the edge swipe did nothing and the app stayed in front. Only the DevDeckHost path was tried on the emulator; the DevDeck.install path shares the tracker, which has unit tests.

🤖 Generated with Claude Code

… one-finger edge swipe

Redaction crash
- Kotlin's Regex.replace creates a new Matcher for every match, and on Android
  each Matcher copies the whole input into native memory. Masking a large
  GraphQL body made thousands of 500 KB copies, which aborted debug apps
  (CheckJNI) or got them killed for low memory.
- NetworkRedaction now uses one Matcher per body and skips bodies that contain
  none of the field names; NetworkLogger.complete masks once, outside the
  StateFlow update that can retry.
- Emulator stress test (4 threads x 5 bodies of 240K chars): 7.1 s per body,
  703 MB native heap and a LOW_MEMORY kill before; 27-124 ms and 21.6 MB after.

Masking
- NetworkLogger.redactedFields is empty by default; auth, cookie, API-key and
  CSRF headers are still masked. NetworkLogger.DEFAULT_REDACTED_FIELDS turns
  field masking back on.

Gestures
- DeckGestures(oneFingerSwipe = true) opens the drawer with a one-finger swipe
  in from its edge (off by default); a 200dp strip of that edge is excluded
  from the system back gesture while the drawer is closed. The old
  DeckGestures constructor and copy are kept as hidden overloads.
@abhishek-3289
abhishek-3289 merged commit 7a1cf8d into main Nov 10, 2026
3 checks passed
@abhishek-3289
abhishek-3289 deleted the fix-redaction-memory branch November 10, 2026 10:58
@github-actions github-actions Bot added this to the Next release milestone Nov 10, 2026
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