You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The demo app at android/app/ (package com.example.gutenbergkit) is the project's reference integrator and the natural canary for library-side regressions. Today it doesn't configure StrictMode at all, so disk I/O on the main thread, leaked closables, registration leaks, etc. introduced inside the library go unnoticed during development and only surface in third-party host apps that do run StrictMode.
This is a demo-app-only change — the library itself stays untouched. The goal is "if the library starts doing something StrictMode-bad, the demo catches it on the next dev build."
Scope
In scope: android/app/ (the :app module). Configure StrictMode in the demo's Application class.
Out of scope: android/Gutenberg/ (the :Gutenberg library module). Do not add StrictMode.allowThreadDiskReads() suppressions to library code as part of this work — if you find violations there, those are bugs to fix or document, not silence here.
Debug builds only: gate the entire setup behind if (BuildConfig.DEBUG). Release builds must not configure StrictMode.
Phased approach
Don't go straight to penaltyDeath(). Two PRs, in this order:
Phase 1 — penaltyLog() everywhere
Find or create the demo's Application subclass. Search for class GutenbergKitApplication in android/app/src/main/java/.
In onCreate(), after super.onCreate(), add a debug-only StrictMode setup:
Verify the manifest registers the Application subclass via android:name. If GutenbergKitApplication isn't yet registered in android/app/src/main/AndroidManifest.xml, register it.
Build, run the demo on a connected device, and exercise the full demo flow:
Launch the app
Tap Bundled Editor → site preparation → enable Native Inserter → load editor
Open the block inserter sheet (the + button)
Tap each category chip
Open the photos rationale (if first run), tap Allow / Reject / Try Again paths
Pick a photo via the Photos tile
Tap Camera tile
Dismiss and reopen the sheet a few times
Type into the search field
Use the overflow menu's "Reset Photo Permissions Prompts"
One DiskReadViolation on first inserter open, from getSharedPreferences("gbk_inserter") in RecentImages.kt's hasPromptedForPhotos. This is the only one the recent media-strip work introduces; the read is sub-millisecond and one-time per process. Document it; don't fix it in this PR.
Possibly older violations from the editor's WebView setup, asset loading, network monitoring registration, and so on. Catalogue what you find.
Add a new entry to docs/code/ (e.g. docs/code/strictmode.md) that:
Documents the configuration.
Lists the known violations the demo currently surfaces (with file:line references).
Names which are intentional (permit) vs. which are tracked for fix in follow-up issues.
References the path to penaltyDeath (Phase 2).
Acceptance: demo app builds, installs, runs without crashing. Logcat shows StrictMode violations. None are unexplained — every violation is either documented or referenced by a tracking issue.
Phase 2 (separate follow-up PR) — penaltyDeath()
After Phase 1's documented violations have been fixed or explicitly permitted, switch the penalty:
.penaltyDeath()
This will crash the demo on any new violation, ensuring future library changes can't quietly regress. Reviewers note: this depends on Phase 1 having addressed every documented violation, so don't merge Phase 2 until that work is in.
Implementation notes
detectAll() is the right starting point. It's a superset that includes detectDiskReads, detectDiskWrites, detectNetwork, detectCustomSlowCalls, detectResourceMismatches, detectUnbufferedIo, and (on VmPolicy) detectLeakedClosableObjects, detectLeakedRegistrationObjects, detectActivityLeaks, detectFileUriExposure, detectCleartextNetwork, detectContentUriWithoutPermission, detectUntaggedSockets, detectImplicitDirectBoot, detectCredentialProtectedWhileLocked, detectIncorrectContextUse, detectUnsafeIntentLaunch. Some of these (detectCleartextNetwork, detectFileUriExposure) may already be tripped by demo-only test paths — note those explicitly.
Application.onCreate() is the right place, not Activity.onCreate(). StrictMode should be set as early as possible in process startup so it covers everything that follows.
Don't enable penaltyDialog(). It interrupts manual testing without adding signal. Stick to log + (eventually) death.
Don't enable penaltyDeath() on VmPolicy either, in Phase 2. VM violations like LeakedClosableObject happen during GC and can crash the app at unpredictable times unrelated to the offending code path. penaltyLog() for VmPolicy is sufficient.
The demo currently has at least one prefs read on inserter open (cited above). That's a known violation introduced in feat(android): add photos and camera media strip to block inserter #479 and is sub-millisecond, one-time per process. Either document-and-permit it via StrictMode.allowThreadDiskReads().resetAfterinside the library helper, or accept the logcat line as cost-of-doing-business and document it. Don't apply a permit at the demo level — that hides the violation from future hosts who would also see it.
Files to touch (expected)
android/app/src/main/java/com/example/gutenbergkit/GutenbergKitApplication.kt — add the StrictMode setup.
android/app/src/main/AndroidManifest.xml — verify or add android:name=".GutenbergKitApplication" on the <application> element.
docs/code/strictmode.md (new) — short doc per the structure above.
Out-of-scope but worth flagging in the PR description
This work makes no library-side changes; if the catalogue surfaces real bugs in :Gutenberg, file follow-up issues, don't fix them here.
Production builds are unaffected — BuildConfig.DEBUG guard.
Phase 2 (penaltyDeath) is its own PR.
Done when
Phase 1 PR opens with the demo configured for penaltyLog() on both policies.
The doc at docs/code/strictmode.md enumerates every violation the configured demo currently surfaces, each labelled either fix-tracked-in-#NNN or intentional-permit-because-X.
The author has manually run through the demo flow above with logcat open and captured the catalogue.
Context
The demo app at
android/app/(packagecom.example.gutenbergkit) is the project's reference integrator and the natural canary for library-side regressions. Today it doesn't configure StrictMode at all, so disk I/O on the main thread, leaked closables, registration leaks, etc. introduced inside the library go unnoticed during development and only surface in third-party host apps that do run StrictMode.This is a demo-app-only change — the library itself stays untouched. The goal is "if the library starts doing something StrictMode-bad, the demo catches it on the next dev build."
Scope
android/app/(the:appmodule). Configure StrictMode in the demo'sApplicationclass.android/Gutenberg/(the:Gutenberglibrary module). Do not addStrictMode.allowThreadDiskReads()suppressions to library code as part of this work — if you find violations there, those are bugs to fix or document, not silence here.if (BuildConfig.DEBUG). Release builds must not configure StrictMode.Phased approach
Don't go straight to
penaltyDeath(). Two PRs, in this order:Phase 1 —
penaltyLog()everywhereFind or create the demo's
Applicationsubclass. Search forclass GutenbergKitApplicationinandroid/app/src/main/java/.In
onCreate(), aftersuper.onCreate(), add a debug-only StrictMode setup:Verify the manifest registers the
Applicationsubclass viaandroid:name. IfGutenbergKitApplicationisn't yet registered inandroid/app/src/main/AndroidManifest.xml, register it.Build, run the demo on a connected device, and exercise the full demo flow:
Capture all StrictMode violations from logcat (filter on tag
StrictMode). Expected violations to see, based on prior review of feat(android): add photos and camera media strip to block inserter #479:DiskReadViolationon first inserter open, fromgetSharedPreferences("gbk_inserter")inRecentImages.kt'shasPromptedForPhotos. This is the only one the recent media-strip work introduces; the read is sub-millisecond and one-time per process. Document it; don't fix it in this PR.Add a new entry to
docs/code/(e.g.docs/code/strictmode.md) that:penaltyDeath(Phase 2).Acceptance: demo app builds, installs, runs without crashing. Logcat shows StrictMode violations. None are unexplained — every violation is either documented or referenced by a tracking issue.
Phase 2 (separate follow-up PR) —
penaltyDeath()After Phase 1's documented violations have been fixed or explicitly permitted, switch the penalty:
This will crash the demo on any new violation, ensuring future library changes can't quietly regress. Reviewers note: this depends on Phase 1 having addressed every documented violation, so don't merge Phase 2 until that work is in.
Implementation notes
detectAll()is the right starting point. It's a superset that includesdetectDiskReads,detectDiskWrites,detectNetwork,detectCustomSlowCalls,detectResourceMismatches,detectUnbufferedIo, and (onVmPolicy)detectLeakedClosableObjects,detectLeakedRegistrationObjects,detectActivityLeaks,detectFileUriExposure,detectCleartextNetwork,detectContentUriWithoutPermission,detectUntaggedSockets,detectImplicitDirectBoot,detectCredentialProtectedWhileLocked,detectIncorrectContextUse,detectUnsafeIntentLaunch. Some of these (detectCleartextNetwork,detectFileUriExposure) may already be tripped by demo-only test paths — note those explicitly.Application.onCreate()is the right place, notActivity.onCreate(). StrictMode should be set as early as possible in process startup so it covers everything that follows.penaltyDialog(). It interrupts manual testing without adding signal. Stick to log + (eventually) death.penaltyDeath()onVmPolicyeither, in Phase 2. VM violations likeLeakedClosableObjecthappen during GC and can crash the app at unpredictable times unrelated to the offending code path.penaltyLog()for VmPolicy is sufficient.StrictMode.allowThreadDiskReads().resetAfterinside the library helper, or accept the logcat line as cost-of-doing-business and document it. Don't apply a permit at the demo level — that hides the violation from future hosts who would also see it.Files to touch (expected)
android/app/src/main/java/com/example/gutenbergkit/GutenbergKitApplication.kt— add the StrictMode setup.android/app/src/main/AndroidManifest.xml— verify or addandroid:name=".GutenbergKitApplication"on the<application>element.docs/code/strictmode.md(new) — short doc per the structure above.Out-of-scope but worth flagging in the PR description
:Gutenberg, file follow-up issues, don't fix them here.BuildConfig.DEBUGguard.penaltyDeath) is its own PR.Done when
penaltyLog()on both policies.docs/code/strictmode.mdenumerates every violation the configured demo currently surfaces, each labelled either fix-tracked-in-#NNN or intentional-permit-because-X.