Error handling was the least-tested code in the app. It only runs when
something goes wrong, which is exactly what a healthy test run avoids, so the
branches a user meets on a bad day were the ones that had never executed. An
audit put it at 4 of 18 fallback branches actually forced by a test.
There was also no mechanism to do better: ConversionWorker constructed
Media3Engine and FFmpegEngine directly, so no test could make either of them
fail. Media3Engine and FFmpegEngine now implement HardwareTranscoder and
SoftwareTranscoder, and ConversionDependencies holds the factories. Workers
are built by WorkManager and the app deliberately carries no DI framework, so
a small settable holder is the least machinery that does the job.
The foreground-service timeout needed different treatment. Its trigger is the
six-hour-per-day budget expiring, which no test can reach, so the decision
moved out of the worker into FailureOutcome. The rule is now verified on the
JVM across every WorkInfo stop reason, including that only the timeout earns a
retry -- retrying a user cancellation would ignore the user, and retrying a
constraint failure would spin.
Thirteen branches are now forced, including both free-space prechecks, both
engines failing, a missing input, and the router bypassing hardware entirely
for MP3. The dynamic fallback is covered twice over: once by injection, and
once by HardwareFallbackTest driving it with genuinely undecodable 4:4:4
footage. Injection alone would prove the plumbing without proving the
condition ever arises in reality.
Five remain unforced and are listed in ConversionDependencies' documentation.
They need a SAF grant to be revoked mid-job, which is not something a test can
arrange.
Media3EngineTest now asserts against the muxed file rather than the engine's
own ExportResult, which is a stronger check anyway: a result object can report
success for a file that will not play.
35 instrumented tests on a Pixel 10 Pro XL and 66 unit tests, 0 failures.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>