Files
LibreMail/app/src/debug/AndroidManifest.xml
T
JMR-devandClaude Opus 4.8 8f8608a430 feat(debug): dev-only pause/halt mail-fetch hook for test harnesses (#393)
The on-device perf harness cannot force a genuinely uncached body fetch: proactive
backfill (#12) and post-sync body prefetch (#88/#89) warm the cache before a test can
open a message. Add a debug-only, adb-reachable hook to pause proactive fetch so a real
uncached open can be measured.

Components:
- DebugFetchGate (src/main): thread-safe in-memory holder of paused FetchScopes
  (BACKFILL, PREFETCH; `all` alias). Defaults to not-paused; HEADER_SYNC and on-demand
  OPEN are never gateable.
- FetchGateReceiver (src/debug only): BroadcastReceiver registered in the debug manifest,
  driven by `adb shell am broadcast -a org.libremail.debug.FETCH_GATE -n .../FetchGateReceiver
  --es action <pause|resume|query> --es scope <backfill,prefetch|all>`. Returns the state as
  ordered-broadcast result data (paused=[...]) for a synchronous read-back.

Enforcement (each read guarded by BuildConfig.DEBUG so R8 strips it from release):
- BackfillWorker.doWork() entry -> skip-and-reschedule when BACKFILL is paused, mirroring
  the existing cache-lock deferral (covers periodic + backfillNow()).
- MailSyncer/MailBackfiller.prefetchIfEnabled -> early-return when PREFETCH is paused.
  openMessage / fetchBodyMarkingSeen / fetchAttachment are deliberately NOT gated.

Debug-only: receiver + <receiver> live wholly in src/debug; every gate read in main is
behind BuildConfig.DEBUG. Verified on assembleRelease that R8 strips DebugFetchGate /
FetchScope / FetchGateReceiver and the log strings from the release APK, and the merged
release manifest has no FETCH_GATE receiver.

PII-free AppLog breadcrumbs on pause/resume/query and on each gate-triggered defer/skip
(scope names only).

Tests: DebugFetchGateTest, BackfillWorkerTest / MailSyncerTest / MailBackfillerTest
enforcement cases, and FetchGateReceiverInstrumentedTest (ordered-broadcast -> gate ->
read-back; gated worker defers while an un-gated path runs).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 20:13:22 -05:00

38 lines
2.1 KiB
XML

<!-- SPDX-License-Identifier: GPL-3.0-or-later -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!--
Debug-only test harness for issue #221 (never merged into a release APK — this manifest belongs to
the debug source set). Hosts ColdOpenCacheProbe in a dedicated ":coldopen" process so an
instrumented test can observe a GENUINE cold open of a pre-encrypted cache: a process where nothing
has yet loaded SQLCipher's process-global native library. The instrumentation process can't offer
that — minting the encrypted fixture (or any earlier test) loads the .so there, masking the 592a797
nativeOpen crash. The provider is exported="false" and inert unless ContentResolver.call() targets
it, so it has no effect on ordinary debug runs.
-->
<application>
<provider
android:name="org.libremail.data.local.coldopen.ColdOpenCacheProbe"
android:authorities="${applicationId}.coldopen"
android:exported="false"
android:process=":coldopen" />
<!--
Debug-only fetch-gate receiver (issue #393; also never merged into a release APK — this
manifest belongs to the debug source set). Lets the on-device perf harness pause proactive
fetch (backfill + body prefetch) via `adb shell am broadcast` so a genuine uncached
message-open can be measured. Must be exported="true" so the adb `shell` UID can reach it by
explicit component (`-n`); it targets the debug BuildConfig.DEBUG-guarded DebugFetchGate only,
carries no PII, and — being debug-only — can never ship. tools:ignore suppresses the
exported-without-permission lint note: a signature permission would (by design) also lock out
the shell UID this hook exists to serve.
-->
<receiver
android:name="org.libremail.debug.FetchGateReceiver"
android:exported="true"
tools:ignore="ExportedReceiver" />
</application>
</manifest>