Skip to content

fix(android): keep pdiff working on density split installs - #700

Merged
sunnylqm merged 2 commits into
masterfrom
fix/android-density-split-copy
Nov 3, 2026
Merged

sunnylqm merged 2 commits into
masterfrom
fix/android-density-split-copy

Conversation

@sunnylqm

@sunnylqm sunnylqm commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Problem

BundledResourceCopier finds patch copies by CRC among the APKs installed on the device. A density split install (Google Play, or bundletool) only has the variants its split_config.<density>.apk carries, so copies of every other density are never found and the whole patch fails with Bundled resource content mismatch (crc32). On an app with @2x and @3x images, 9 of 17 copies were missing at every density tested, so its Play users could not take a pdiff at all.

Fix

When a copy's CRC is not found, its targets are filled from the variant Android resolves for that resource, only if all of these hold:

  • the install has density splits;
  • every target is a drawable-* path whose density is not installed;
  • the path match did not already show drift;
  • the resource resolves to an installed variant, of a different density than the target.

A copy of an installed density, a resource that was removed, and content that moved into an installed density still fail as before.

The filled file holds the installed variant, so a later density change reads an existing file instead of hitting ENOENT. Its pixel size may not match its directory.

Verification

  • BundledResourceCopierTest (new, not run by CI): 6 cases on the density decision.
  • Probe app, split installs on API 26 and 34, crunchPngs on and off: unfixed fails, fixed succeeds; switching among xhdpi/xxhdpi/xxxhdpi loads every image; drift, removal and moved content fail; only changing a density that is not installed succeeds, as intended; plain APK unchanged; AAB baseline passes.
  • Production app config (R8, shrinkResources, crunchPngs false), sideload APK as baseline, Play AAB split installed by bundletool, API 34: unfixed fails on 9 entries; fixed succeeds on xhdpi, xxhdpi and xxxhdpi, and images load after density changes.

Not covered: splits delivered by Play itself (to be checked on an internal track after release), API 24/25.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Android installations using density-specific APK splits can now use an available bundled image variant when the requested density is missing. Missing resources or content mismatches still cause the update to fail.
  • Documentation
    • Clarified how density-specific resources are handled during bundle hash checks.

A split install only has the density variants its split carries, so every
patch copy of another density looked like content drift and failed the patch.
Fill those targets from the variant the resource has installed. Copies of an
installed density, and paths present with other content, still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Caution

Review failed

The pull request is closed.

Walkthrough

The Android resource copier detects installed density splits. When a requested source is absent without CRC drift, it can use eligible bundled resources at another density to populate target paths.

Changes: Android density-variant fallback

Layer / File(s) Summary
Density metadata and eligibility
android/src/main/java/cn/reactnative/modules/update/BundledResourceCopier.java, android/src/test/java/cn/reactnative/modules/update/BundledResourceCopierTest.java
The copier extracts installed density qualifiers, retains resolved resource density and target paths, and checks whether all targets have a matching bundled resource at another density. Tests cover split-name parsing and substitution eligibility.
Fallback copy and drift handling
android/src/main/java/cn/reactnative/modules/update/BundledResourceCopier.java, docs/BUNDLEHASH_MIGRATION.md
The copier does not substitute after a path match fails CRC validation. If the source is absent without CRC drift, it writes eligible substitutes, records write failures, and logs successful substitutions. The migration documentation describes this behavior.

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

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant BundledResourceCopier
  participant InstalledApkPaths
  participant BundledResourceArchive
  participant TargetPaths
  BundledResourceCopier->>InstalledApkPaths: Extract installed density qualifiers
  BundledResourceCopier->>BundledResourceArchive: Resolve eligible resource at another density
  BundledResourceArchive-->>BundledResourceCopier: Return matching archive entry
  BundledResourceCopier->>TargetPaths: Write substitute resources
Loading
Merge Risk: Low · previous review 90ff8

Some night-mode images could display the day variant after a density-split patch. Restricting substitution to density-only targets would address this bounded risk.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed 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 "fix(android): keep pdiff working on density split installs" names the main change: a fix for patch failures on Android density-split installs. The raw summary and PR objectives both describ…
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.
Full details: Title check

Explanation

The title "fix(android): keep pdiff working on density split installs" names the main change: a fix for patch failures on Android density-split installs. The raw summary and PR objectives both describe filling missing density-split resource copies from the installed density variant, so the title matches the changeset. It uses the conventional commit prefix and is 58 characters, within a concise length. It does not name the specific mechanism (substitution of installed density variants), but it is not overly broad for the primary purpose.

Full details: Docstring Coverage

Explanation

Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 9 functions across 2 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Tip

🎯 Customize your risk assessments

Guide how CodeRabbit assesses merge risk and security architecture risk. Highlight sensitive changes and explain your security boundaries using Merge Risk Instructions and Security Risk Instructions in your review settings. Security architecture risk assessments require the Advanced plan or above.

✅ Automatic approvals, with your rules

Let CodeRabbit approve pull requests once required threads are resolved, pre-merge checks pass, and your risk limits are met. Enable Automatic approvals in review settings, with overrides for teams or file paths.

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

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 8ef15aa5-4d21-4778-8861-a2556e43f739
Commits

Reviewing files that changed from the base of the PR and between 4620119 and 90ff8d9.

Files selected for processing: 3
  • android/src/main/java/cn/reactnative/modules/update/BundledResourceCopier.java
  • android/src/test/java/cn/reactnative/modules/update/BundledResourceCopierTest.java
  • docs/BUNDLEHASH_MIGRATION.md

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  • Fix comments: Fix CodeRabbit comments on this PR

A target like drawable-night-hdpi resolved from the current configuration, so
a day variant could land in the night directory. Such targets fail as drift.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sunnylqm
sunnylqm merged commit 0b24287 into master Nov 3, 2026
9 of 11 checks passed
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