Update install failures become visible: blocked, aborted, failed (D-155)
The PackageInstaller session's final status now reaches UpdateRepository: InstallResultReceiver hands it by session id to the waiting AndroidApkInstaller call (ApkInstaller.install returns a PendingInstall). installOutcome() maps STATUS_FAILURE_BLOCKED to UpdateFailure.Blocked, STATUS_FAILURE_ABORTED back to Available without an error, and every other failure to UpdateFailure.Install with the installer's EXTRA_STATUS_MESSAGE. The cached APK is deleted once the installer answers, so "Try again" downloads again. UpdateBanner's Failed variant shows the reason on S-4 and S-22; two core:design strings (en/sv) with their docs/ux/strings.csv rows. Unit tests for the mapping, the repository outcomes and the receiver; goldens: update_banner re-recorded, S-17-install-blocked, S-17-install-failed and s22_about_install_blocked new. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
This commit is contained in:
@@ -34,10 +34,28 @@ sealed interface UpdateState {
|
||||
data object None : UpdateState
|
||||
data class Available(val info: UpdateInfo) : UpdateState
|
||||
data class Downloading(val info: UpdateInfo, val progress: Float) : UpdateState
|
||||
data class Failed(val info: UpdateInfo) : UpdateState
|
||||
|
||||
/** The download or the install failed (AC-16.4, D-155); [reason] picks the banner's text, "Försök igen" downloads again. */
|
||||
data class Failed(val info: UpdateInfo, val reason: UpdateFailure = UpdateFailure.Download) : UpdateState
|
||||
|
||||
data class NeedsInstallPermission(val info: UpdateInfo) : UpdateState
|
||||
}
|
||||
|
||||
/** Why [UpdateState.Failed] (D-155). The downloaded file is deleted in every case. */
|
||||
sealed interface UpdateFailure {
|
||||
/** No answer, an error, or the size or SHA-256 did not match (AC-16.4). */
|
||||
data object Download : UpdateFailure
|
||||
|
||||
/** The installer refused the install as blocked (`STATUS_FAILURE_BLOCKED`): the phone's security settings. */
|
||||
data object Blocked : UpdateFailure
|
||||
|
||||
/**
|
||||
* Any other installer failure (invalid, conflict, storage, incompatible, timeout, generic). [detail] is the
|
||||
* installer's own status message, null when it gave none; it names packages and error codes, never personal data.
|
||||
*/
|
||||
data class Install(val detail: String?) : UpdateFailure
|
||||
}
|
||||
|
||||
/** The outcome of [UpdateRepository.check] and [UpdateRepository.checkNow] (S-22, AC-16.6). */
|
||||
sealed interface UpdateCheck {
|
||||
/** No newer APK is published (or nothing is published); debug builds, which never check (AC-16.5), report this too. */
|
||||
|
||||
Reference in New Issue
Block a user