Linear: https://linear.app/engineereddev/issue/ENG-270 (M4 gate; bug from ENG-266)
The M4 gate's release-build run found that Share on the download-complete notification did nothing: the ACTION_CHOOSER wrapper carried a pneumo://download/share data URI (for PendingIntent identity), so it resolved to no activity (ActivityNotFoundException in SystemUI). Home's Share worked.
What's in this PR (7 files):
- New non-exported, no-display trampoline
notify/DownloadShareActivity(taskAffinity="",noHistory,excludeFromRecents), mirroringDownloadOpenActivity. The notification's Share PendingIntent targets it with the file's content URI and MIME as intent data/type (per-notification identity); it starts a data-free system chooser for that file and finishes. Onlycontent://URIs are accepted. DownloadActions.kt: Share PendingIntent built for the trampoline. Notification ids/tags, group/summary rules and the progress throttle are unchanged.- Tests:
DownloadActionsTest(fails on the old code on API 26 and 34: the Share intent resolves; two files get two distinct Share targets);RealServerSmokeTestnow fires the completed notification's real Share PendingIntent and checks the chooser's file URI, MIME, clip data and read grant. docs/SPEC.md§14.2: one sentence noting the two library-merged permissions (WAKE_LOCKfrom WorkManager, the signature-levelDYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSIONfrom androidx.core), found by the gate's merged-manifest check.
Verify (lead, on 0261414):
mise run check:android→ exit 0./gradlew testDebugUnitTest --rerun→ exit 0 (355 tests, 0 failures)mise run e2e:android→ exit 0 (real-server smoke incl. Share; secret scan 0 matches; full cleanup)
🤖 Generated with Claude Code