diff --git a/app/src/main/java/org/thoughtcrime/securesms/apkupdate/ApkUpdateInstaller.kt b/app/src/main/java/org/thoughtcrime/securesms/apkupdate/ApkUpdateInstaller.kt index b4b5c0dc05..ef0ff39a1a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/apkupdate/ApkUpdateInstaller.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/apkupdate/ApkUpdateInstaller.kt @@ -5,6 +5,7 @@ package org.thoughtcrime.securesms.apkupdate +import android.app.DownloadManager import android.app.PendingIntent import android.content.Context import android.content.Intent @@ -53,6 +54,13 @@ object ApkUpdateInstaller { return } + if (!isDownloadSuccessful(context, downloadId)) { + Log.w(TAG, "DownloadId matches, but the download was not successful. The download may have failed due to a network issue. Clearing state and re-checking for updates.") + SignalStore.apkUpdate.clearDownloadAttributes() + AppDependencies.jobManager.add(ApkUpdateJob()) + return + } + if (!isMatchingDigest(context, downloadId, digest)) { Log.w(TAG, "DownloadId matches, but digest does not! Bad download or inconsistent state. Failing and clearing state.") SignalStore.apkUpdate.clearDownloadAttributes() @@ -136,6 +144,35 @@ object ApkUpdateInstaller { } } + private fun isDownloadSuccessful(context: Context, downloadId: Long): Boolean { + val query = DownloadManager.Query().setFilterById(downloadId) + val cursor = context.getDownloadManager().query(query) + + return cursor.use { cursor -> + if (cursor.moveToFirst()) { + val status = cursor + .getColumnIndex(DownloadManager.COLUMN_STATUS) + .takeUnless { it == -1 } + ?.let { cursor.getInt(it) } ?: DownloadManager.STATUS_FAILED + + if (status == DownloadManager.STATUS_SUCCESSFUL) { + return@use true + } + + val reason = cursor + .getColumnIndex(DownloadManager.COLUMN_REASON) + .takeUnless { it == -1 } + ?.let { cursor.getInt(it) } + + Log.w(TAG, "Download not successful. Status: $status, Reason: $reason") + false + } else { + Log.w(TAG, "Download ID $downloadId not found in DownloadManager.") + false + } + } + } + private fun isMatchingDigest(context: Context, downloadId: Long, expectedDigest: ByteArray): Boolean { return try { FileInputStream(context.getDownloadManager().openDownloadedFile(downloadId).fileDescriptor).use { stream ->