Spec: Phase 7 — Offline downloads: into the cache the consumer opened, resumable, on a battery-aware schedule
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 18/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Domain
- mobile-dev
Research direction
This is an epic with no code change yet; begin with child #238, the ADR, reading ADR-0010, ADR-0012, PRD.md §3.5 and docs/modules.md for the dependency rule. Code starts after the harness prefactor #239, then the tracer bullet #240, which downloads clear content into the ContentKeyedCache in superplayer-offline and plays it through setMediaRequest. Done means the download plays with zero network requests and can be removed.
Written by the indexing model from the issue text.
Description
Problem Statement
Phase 6 made protected content play and made an offline licence something a consumer can acquire, hold, renew and release. Nothing persists the media: superplayer-offline is an empty placeholder, and PRD.md §3.5's download stack is unbuilt.
- The storage is ready and nobody writes to it. ADR-0010 built a pinned region into
ContentKeyedCache"so that Phase 7's downloads have somewhere eviction cannot reach", and records a standing obligation thatsuperplayer-offlineshares that cache and its key policy rather than opening a second one. - The licence half is ready and bound to nothing. ADR-0012 closes on the matching obligation: Phase 7's downloads read
OfflineLicenceStoreand its playback-versus-licence expiry split rather than keeping their own. - F4's battery requirement has no home. Background downloads draining battery is one of
PRD.mdPart 1's named problems; §3.5 answers it withWorkManagerconstraints (UNMETERED, battery not low, storage not low), and none exist. - The module's declared dependency is
corealone, while the work needs the cache (phase 4) and, for protected content, the DRM module (phase 6). Both are allowed bydocs/modules.md's rule; which of them a clear-only app pays for is a decision, not a default.
Solution
Ship superplayer-offline (PRD.md §3.5) on the seams earlier phases built, as Phases 3–6 shipped theirs.
One cache, still. A download writes into the ContentKeyedCache the consumer opened, under the same content keys a player reads, pinned for as long as the download exists. A player plays downloaded content through setMediaRequest with no network, because the bytes are where it already looks.
Storage and scheduling stay the consumer's. The consumer names the directory and the budget (ADR-0010 rule 1); the DownloadService subclass, its manifest entry and the foreground-service permissions are the app's (ADR-0007 rule 4's shape). What is correctness — resuming rather than refetching, stopping on a lapsed constraint rather than failing, failing one item on a full disk rather than the queue — is on for everyone.
The licence follows the download. A protected download acquires its offline licence as part of the download, plays with zero licence requests, reports an expired licence before playback, and releases it on delete.
Nothing here is testable unless the harness can drive a download first. Media3's DownloadManager loads on threads of its own, through a data source the harness does not own, and WorkManager constraints have no statement in DeviceStatement. That machinery is a prefactor, and it comes first.
Scope
| # | Issue | What it lands |
|---|---|---|
| #238 | ADR-0013 | Module dependencies, the public surface, one cache, constraints as correctness or policy, the licence binding |
| #239 | Harness downloads | A download over the harness transport and clock; process death and WorkManager constraints stated |
| #240 | Tracer bullet | Download clear content, play it with zero requests, remove it |
| #241 | Track selection | A sensible rendition, declared audio languages and subtitles, not the whole ladder |
| #242 | Resumable | Across process death and network loss, without refetching what is held |
| #243 | WorkManager policy | Unmetered, battery not low, storage not low; survives reboot |
| #244 | Storage full | One item fails typed; the queue carries on |
| #245 | Licence binding | Acquire with the download, play offline, expiry before playback, release on delete |
| #246 | Demo | The consumer's recipe: service, permissions, a downloads screen |
| #247 | Phase exit | Process death, network loss, reboot and the battery profiler, on a device |
Order: the ADR and the harness first; they gate everything. The clear-content download is the tracer bullet, and the rest hang off it. Each child names its blockers.
Exit criteria
Per PRD.md Part 4:
- A download survives process death, network loss, and reboot.
- Battery policy verified with a battery profiler.
- No Media3
@UnstableApitype in the module's public API, and a player built without it registers and allocates nothing. ./gradlew assemble checkstays green.
Non-goals
- A second cache or a second key policy. ADR-0010 settled where downloaded bytes live.
- A second licence store. ADR-0012 settled where an offline licence lives.
- Scheduling renewal. ADR-0012 rule 10: the library reports and the consumer calls.
- Moving a benchmark number. Download throughput and battery cost are reported here; tuning them is Phase 10's.
- TV-specific download UX.
superplayer-tvis Phase 8.
- Dominant language
- Kotlin
- Stars
- 1
- Forks
- 0
- Avg merge
- 3h 32m
- Merged PRs (30d)
- 64
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from ramesh130/superplayer
-
bug need-device
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
ramesh130/superplayer#495 ·
Maintainers usually reply within 1 day
-
Flakes (Android): AudioCapabilityChangeTest reselect wait and DownloadConditionsTest metered stopOpenready-for-agent
Difficulty 4/5 1-2 days Newbie friendliness 28/100
ramesh130/superplayer#526 ·
Maintainers usually reply within 1 day
-
ios ready-for-agent
Difficulty 4/5 3-5 days Newbie friendliness 28/100
ramesh130/superplayer#518 ·
Maintainers usually reply within 1 day
-
ready-for-agent
Difficulty 4/5 1-2 days Newbie friendliness 58/100
ramesh130/superplayer#501 ·
Maintainers usually reply within 1 day
-
ready-for-agent
Difficulty 4/5 3-5 days Newbie friendliness 48/100
ramesh130/superplayer#500 ·
Maintainers usually reply within 1 day
All issues in ramesh130/superplayer
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
liberation-data/drivine-cypher-spec#67 ·
Maintainers usually reply within 1 day
-
feature
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
-
documentation good first issue help wanted P2 roadmap-v4
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
maziyarpanahi/openmed#5425 ·
Maintainers usually reply within 3 days
-
Difficulty 1/5 Under an hour Newbie friendliness 80/100
pengchujin/aerial-tv#1355 · 3 comments ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
QuranHub/quranhub-android#354 ·
Maintainers usually reply within 2 days