Skip to content

Harden Android-only release validation#49

Merged
ModerRAS merged 2 commits into
masterfrom
fix/android-ci-webcontrol-stop
Jul 16, 2026
Merged

Harden Android-only release validation#49
ModerRAS merged 2 commits into
masterfrom
fix/android-ci-webcontrol-stop

Conversation

@ModerRAS

@ModerRAS ModerRAS commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • make WebControl stop pause and close the player through normal navigation so PlayerViewModel saves progress and fully releases the backend
  • make startup diagnostics reuse case-insensitive MediaStore paths and guard API 29-only calls while declaring the manifest WorkManager dependency
  • run every unit-test task in CI, make lint blocking, and gate release/nightly publishing on build and lint
  • localize lint suppressions to deliberate Media3 experimental API files instead of adding a global baseline

Validation

  • ./gradlew test lint :app:assembleDebug (1084 tasks, successful)
  • focused app/data/player/ui-tv/web-control unit and lint tasks
  • HK1 release v2.0.588: install/update, startup, local source scan, library, search, detail/progress, settings, WebUI auth/API, Exo, embedded mpv, MediaCodec, seek, embedded/external subtitles, Simplified Chinese preference, manual override, and automatic next episode
  • temporary playback preferences restored to return-to-detail / auto subtitles / Standard Exo

Device follow-up

  • HK1 reproduced the pre-fix WebControl stop issue on v2.0.588. Local release signing credentials are unavailable, so the stop/diagnostics fixes are covered by focused unit tests and full build/lint; final on-device confirmation requires the next same-signature release APK.

Version

  • keep baseAppVersionName at 2.0.0; this is a patch-level reliability fix on the existing v2.0.x line

Summary by CodeRabbit

  • New Features
    • Added a TV player screen with playback controls, picture/audio/subtitle options, speed selection, error recovery, and remote-control navigation.
    • Added web-control support for closing the active player.
  • Bug Fixes
    • Improved web-control stop behavior so playback pauses before the player closes and reports an idle state.
    • Improved reliability when locating startup diagnostic and download entries on newer Android versions.
  • Quality Improvements
    • Strengthened automated testing and lint validation.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ModerRAS, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 45 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cacefaed-e0de-4d22-ac25-f6d6660ce232

📥 Commits

Reviewing files that changed from the base of the PR and between 90f70e1 and 5554b9d.

📒 Files selected for processing (2)
  • app/src/main/kotlin/com/miruplay/tv/StartupProbeProvider.kt
  • data/src/main/kotlin/com/miruplay/tv/data/logging/EarlyStartupDiagnostics.kt
📝 Walkthrough

Walkthrough

The pull request adds web-controlled player closure, updates MediaStore diagnostics lookup logic, adds player-related build support, suppresses selected player diagnostics, and strengthens CI job ordering and lint enforcement.

Changes

Player control and platform updates

Layer / File(s) Summary
Web-control player close and stop flow
web-control/src/main/kotlin/..., web-control/src/test/kotlin/...
STOP pauses playback, queues a close-player command, returns idle status, and validates successful and failed close requests.
Player navigation integration
app/src/main/kotlin/..., app/build.gradle.kts, ui-tv/src/main/kotlin/...
The app handles close-player navigation for the player route, adds WorkManager runtime support, and adds the player screen source.
MediaStore diagnostics lookup
app/src/main/kotlin/..., data/src/main/kotlin/...
Public download entries are located by display name and case-insensitive relative-path matching through shared or updated cursor logic.
CI and player build validation
.github/workflows/ci.yml, player-core/src/main/kotlin/...
CI runs unit tests, enforces lint success, orders release and nightly jobs after build and lint, and adds file-level player diagnostic suppressions.

Estimated code review effort: 3 (Moderate) | ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the PR’s main theme of hardening Android-only release validation and CI/release gating.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/android-ci-webcontrol-stop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
app/src/main/kotlin/com/miruplay/tv/StartupProbeProvider.kt (1)

244-268: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer getColumnIndexOrThrow over hardcoded indices.

Although the projection explicitly defines the column order, it is safer and more idiomatic to resolve cursor column indices dynamically rather than relying on hardcoded indices like 0 and 1.

  • app/src/main/kotlin/com/miruplay/tv/StartupProbeProvider.kt#L244-L268: Retrieve indices for _ID and RELATIVE_PATH using getColumnIndexOrThrow and use them in place of getLong(0) and getString(1).
  • data/src/main/kotlin/com/miruplay/tv/data/logging/EarlyStartupDiagnostics.kt#L179-L199: Retrieve indices for _ID and RELATIVE_PATH using getColumnIndexOrThrow and use them in place of getLong(0) and getString(1).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/kotlin/com/miruplay/tv/StartupProbeProvider.kt` around lines 244
- 268, Replace hardcoded cursor column positions with getColumnIndexOrThrow in
findPublicDownloadUri within
app/src/main/kotlin/com/miruplay/tv/StartupProbeProvider.kt:244-268, resolving
_ID and RELATIVE_PATH before iteration and using those indices for getLong and
getString. Apply the same change in the corresponding query logic in
data/src/main/kotlin/com/miruplay/tv/data/logging/EarlyStartupDiagnostics.kt:179-199.
player-core/src/main/kotlin/com/miruplay/tv/player/ExperimentalHdrSdrVideoGraphFactory.kt (1)

1-2: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Move the Media3 opt-in to the affected declarations.

  • player-core/src/main/kotlin/com/miruplay/tv/player/ExperimentalHdrSdrVideoGraphFactory.kt: annotate ExperimentalHdrSdrPreviewingVideoGraphFactory with @OptIn(UnstableApi::class) and drop the file suppression.
  • player-core/src/main/kotlin/com/miruplay/tv/player/ExperimentalHdrSurfaceMediaCodecVideoRenderer.kt: the class is already @UnstableApi, so the file suppression is redundant.
  • player-core/src/main/kotlin/com/miruplay/tv/player/PlaybackDataSourceFactory.kt: annotate PlaybackDataSourceFactory with @OptIn(UnstableApi::class) and drop the file suppression.

This keeps the opt-in scope narrow and leaves future unsafe usages exposed to the compiler.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@player-core/src/main/kotlin/com/miruplay/tv/player/ExperimentalHdrSdrVideoGraphFactory.kt`
around lines 1 - 2, Replace the file-level suppression in
player-core/src/main/kotlin/com/miruplay/tv/player/ExperimentalHdrSdrVideoGraphFactory.kt:1-2
with `@OptIn`(UnstableApi::class) on
ExperimentalHdrSdrPreviewingVideoGraphFactory. Remove the redundant suppression
in
player-core/src/main/kotlin/com/miruplay/tv/player/ExperimentalHdrSurfaceMediaCodecVideoRenderer.kt:1-2
because the class is already annotated with `@UnstableApi`. In
player-core/src/main/kotlin/com/miruplay/tv/player/PlaybackDataSourceFactory.kt:1-2,
annotate PlaybackDataSourceFactory with `@OptIn`(UnstableApi::class) and remove
the file-level suppression.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app/src/main/kotlin/com/miruplay/tv/StartupProbeProvider.kt`:
- Around line 244-268: Replace hardcoded cursor column positions with
getColumnIndexOrThrow in findPublicDownloadUri within
app/src/main/kotlin/com/miruplay/tv/StartupProbeProvider.kt:244-268, resolving
_ID and RELATIVE_PATH before iteration and using those indices for getLong and
getString. Apply the same change in the corresponding query logic in
data/src/main/kotlin/com/miruplay/tv/data/logging/EarlyStartupDiagnostics.kt:179-199.

In
`@player-core/src/main/kotlin/com/miruplay/tv/player/ExperimentalHdrSdrVideoGraphFactory.kt`:
- Around line 1-2: Replace the file-level suppression in
player-core/src/main/kotlin/com/miruplay/tv/player/ExperimentalHdrSdrVideoGraphFactory.kt:1-2
with `@OptIn`(UnstableApi::class) on
ExperimentalHdrSdrPreviewingVideoGraphFactory. Remove the redundant suppression
in
player-core/src/main/kotlin/com/miruplay/tv/player/ExperimentalHdrSurfaceMediaCodecVideoRenderer.kt:1-2
because the class is already annotated with `@UnstableApi`. In
player-core/src/main/kotlin/com/miruplay/tv/player/PlaybackDataSourceFactory.kt:1-2,
annotate PlaybackDataSourceFactory with `@OptIn`(UnstableApi::class) and remove
the file-level suppression.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2984559f-592b-439f-957f-6471eef6b6e6

📥 Commits

Reviewing files that changed from the base of the PR and between 3118875 and 90f70e1.

📒 Files selected for processing (18)
  • .github/workflows/ci.yml
  • app/build.gradle.kts
  • app/src/main/kotlin/com/miruplay/tv/MainActivity.kt
  • app/src/main/kotlin/com/miruplay/tv/StartupProbeProvider.kt
  • data/src/main/kotlin/com/miruplay/tv/data/logging/EarlyStartupDiagnostics.kt
  • player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt
  • player-core/src/main/kotlin/com/miruplay/tv/player/ExoVideoEffectMapping.kt
  • player-core/src/main/kotlin/com/miruplay/tv/player/ExperimentalHdrSdrVideoGraphFactory.kt
  • player-core/src/main/kotlin/com/miruplay/tv/player/ExperimentalHdrSurfaceMediaCodecVideoRenderer.kt
  • player-core/src/main/kotlin/com/miruplay/tv/player/ExperimentalRenderersFactory.kt
  • player-core/src/main/kotlin/com/miruplay/tv/player/PlaybackDataSourceFactory.kt
  • player-core/src/main/kotlin/com/miruplay/tv/player/PlaybackMediaCodecSelector.kt
  • player-core/src/main/kotlin/com/miruplay/tv/player/VideoSignalFormatResolver.kt
  • ui-tv/src/main/kotlin/com/miruplay/tv/ui/player/PlayerScreen.kt
  • web-control/src/main/kotlin/com/miruplay/tv/webcontrol/WebControlNavigator.kt
  • web-control/src/main/kotlin/com/miruplay/tv/webcontrol/WebControlService.kt
  • web-control/src/test/kotlin/com/miruplay/tv/webcontrol/WebControlNavigatorTest.kt
  • web-control/src/test/kotlin/com/miruplay/tv/webcontrol/WebControlPlaybackStopTest.kt

@ModerRAS
ModerRAS merged commit 457bdab into master Jul 16, 2026
7 checks passed
@ModerRAS
ModerRAS deleted the fix/android-ci-webcontrol-stop branch July 16, 2026 06:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant