Fix: Prevent crash when app is launched during automatic backup - #2221
Closed
d4rken wants to merge 2 commits into
Closed
Fix: Prevent crash when app is launched during automatic backup#2221d4rken wants to merge 2 commits into
d4rken wants to merge 2 commits into
Conversation
Remove @androidentrypoint from all 4 BroadcastReceivers and use manual EntryPointAccessors with an isValidHiltContext() guard. During Android Auto Backup, receivers get a RestrictedContext whose applicationContext is a plain Application (not @HiltAndroidApp), causing Hilt injection to crash. On Android <= 13, this crash can poison subsequent app launches. Closes #1274
d4rken
force-pushed
the
fix/backup-receiver-crash-1274
branch
from
March 9, 2026 15:16
544bc7e to
c584fea
Compare
BroadcastReceiverBackupGuardTest referenced internal constants across module boundaries, causing compilation failures in both testFoss and testGplay CI jobs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Fixed a crash that could happen when SD Maid was launched while Android's automatic backup was running. On Android 13 and below, this crash could also break subsequent app launches until the device was restarted.
Developer TLDR
@AndroidEntryPointfrom all 4BroadcastReceivers (SchedulerRestoreReceiver,UnarchiveReceiver,UninstallWatcherReceiver,ExternalWatcherTaskReceiver)super.onReceive()before any user code, making it impossible to guard with@AndroidEntryPoint. Switched to manualEntryPointAccessors.fromApplication()per Dagger team recommendationContext.isValidHiltContext()helper inInjectionHelpers.ktand consolidated existingService.isValidAndroidEntryPoint()to delegate to itEntryPointAccessorsCorpseFinderSettingsinjection fromExternalWatcherTaskReceiverBroadcastReceiverBackupGuardTestregression test verifying all 4 receivers silently return with a restricted contextBackground & research
Root cause
When Android Auto Backup runs, it invokes registered
BroadcastReceivers with aRestrictedContextwhoseapplicationContextis a plainandroid.app.Application— not our@HiltAndroidApp App. Hilt's Gradle plugin performs bytecode transformation on@AndroidEntryPointreceivers, inserting asuper.onReceive()call at the very beginning ofonReceive()— before any user code. This makes it impossible to add a guard check while using@AndroidEntryPoint.On Android <= 13, there's a platform bug (Google issue #160946170) where crashing during backup causes the "restricted" flag to persist, breaking subsequent app launches until the device is restarted.
Why
EntryPointAccessorsinstead of alternatives@AndroidEntryPoint+ add guard inonReceivesuper.onReceive()before our codeandroid:allowBackup="false"BackupAgent@AndroidEntryPoint+ manualEntryPointAccessorsKnown tradeoff
With
@AndroidEntryPoint, adding a dependency was just@Inject lateinit var foo: Foo. Now someone needs to also add the method to theReceiverEntryPointinterface and call it manually. Forgetting the interface method is a compile error (Dagger can't find the binding), so it's not silent — just more friction.Related issues
Closes #1274