diff --git a/app/src/main/java/org/thoughtcrime/securesms/apkupdate/ApkUpdatePackageInstallerReceiver.kt b/app/src/main/java/org/thoughtcrime/securesms/apkupdate/ApkUpdatePackageInstallerReceiver.kt index c988d2c5ba..05dd23601a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/apkupdate/ApkUpdatePackageInstallerReceiver.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/apkupdate/ApkUpdatePackageInstallerReceiver.kt @@ -12,6 +12,7 @@ import android.content.pm.PackageInstaller import org.signal.core.util.getParcelableExtraCompat import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.apkupdate.ApkUpdateNotifications.FailureReason +import org.thoughtcrime.securesms.keyvalue.SignalStore /** * This is the receiver that is triggered by the [PackageInstaller] to notify of various events. Package installation is initiated @@ -36,6 +37,7 @@ class ApkUpdatePackageInstallerReceiver : BroadcastReceiver() { when (statusCode) { PackageInstaller.STATUS_SUCCESS -> { Log.i(TAG, "Update installed successfully!") + SignalStore.apkUpdate().lastApkUploadTime = SignalStore.apkUpdate().pendingApkUploadTime ApkUpdateNotifications.showAutoUpdateSuccess(context) } PackageInstaller.STATUS_PENDING_USER_ACTION -> handlePendingUserAction(context, userInitiated, intent!!) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ApkUpdateJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/ApkUpdateJob.kt index c63568a89d..270360459b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ApkUpdateJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ApkUpdateJob.kt @@ -81,8 +81,9 @@ class ApkUpdateJob private constructor(parameters: Parameters) : BaseJob(paramet Log.d(TAG, "Got descriptor: $updateDescriptor") } - if (updateDescriptor.versionCode > getCurrentAppVersionCode()) { - Log.i(TAG, "Newer version code available. Current: ${getCurrentAppVersionCode()}, Update: ${updateDescriptor.versionCode}") + val currentVersionCode = getCurrentAppVersionCode() + if (updateDescriptor.versionCode > currentVersionCode || (updateDescriptor.versionCode == currentVersionCode && (updateDescriptor.uploadTimestamp ?: 0) > SignalStore.apkUpdate().lastApkUploadTime)) { + Log.i(TAG, "Newer version code available. Current: (versionCode: ${getCurrentAppVersionCode()}, uploadTime: ${SignalStore.apkUpdate().lastApkUploadTime}), Update: (versionCode: ${updateDescriptor.versionCode}, uploadTime: ${updateDescriptor.uploadTimestamp})") val digest: ByteArray = Hex.fromStringCondensed(updateDescriptor.digest) val downloadStatus: DownloadStatus = getDownloadStatus(updateDescriptor.url, digest) @@ -93,10 +94,10 @@ class ApkUpdateJob private constructor(parameters: Parameters) : BaseJob(paramet handleDownloadComplete(downloadStatus.downloadId) } else if (downloadStatus.status == DownloadStatus.Status.MISSING) { Log.i(TAG, "Download status missing, starting download...") - handleDownloadStart(updateDescriptor.url, updateDescriptor.versionName, digest) + handleDownloadStart(updateDescriptor.url, updateDescriptor.versionName, digest, updateDescriptor.uploadTimestamp ?: 0) } } else { - Log.d(TAG, "Version code is the same or older than our own. Current: ${getCurrentAppVersionCode()}, Update: ${updateDescriptor.versionCode}") + Log.d(TAG, "Version code is the same or older than our own. Current: (versionCode: ${getCurrentAppVersionCode()}, uploadTime: ${SignalStore.apkUpdate().lastApkUploadTime}), Update: (versionCode: ${updateDescriptor.versionCode}, uploadTime: ${updateDescriptor.uploadTimestamp})") } SignalStore.apkUpdate().lastSuccessfulCheck = System.currentTimeMillis() @@ -155,7 +156,7 @@ class ApkUpdateJob private constructor(parameters: Parameters) : BaseJob(paramet return DownloadStatus(DownloadStatus.Status.MISSING, -1) } - private fun handleDownloadStart(uri: String?, versionName: String?, digest: ByteArray) { + private fun handleDownloadStart(uri: String?, versionName: String?, digest: ByteArray, uploadTimestamp: Long) { deleteExistingDownloadedApks(context) val downloadRequest = DownloadManager.Request(Uri.parse(uri)).apply { @@ -169,7 +170,7 @@ class ApkUpdateJob private constructor(parameters: Parameters) : BaseJob(paramet val downloadId = context.getDownloadManager().enqueue(downloadRequest) // DownloadManager will trigger [UpdateApkReadyListener] when finished via a broadcast - SignalStore.apkUpdate().setDownloadAttributes(downloadId, digest) + SignalStore.apkUpdate().setDownloadAttributes(downloadId, digest, uploadTimestamp) } private fun handleDownloadComplete(downloadId: Long) { @@ -216,7 +217,10 @@ class ApkUpdateJob private constructor(parameters: Parameters) : BaseJob(paramet val url: String? = null, @JsonProperty("sha256sum") - val digest: String? = null + val digest: String? = null, + + @JsonProperty + val uploadTimestamp: Long? = null ) private class DownloadStatus(val status: Status, val downloadId: Long) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/ApkUpdateValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/ApkUpdateValues.kt index e54bb9a963..a37eda3dff 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/ApkUpdateValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/ApkUpdateValues.kt @@ -11,6 +11,8 @@ internal class ApkUpdateValues(store: KeyValueStore) : SignalStoreValues(store) private const val DIGEST = "apk_update.digest" private const val AUTO_UPDATE = "apk_update.auto_update" private const val LAST_SUCCESSFUL_CHECK = "apk_update.last_successful_check" + private const val LAST_APK_UPLOAD_TIME = "apk_update.last_apk_upload_time" + private const val PENDING_APK_UPLOAD_TIME = "apk_update.pending_apk_upload_time" } override fun onFirstEverAppLaunch() = Unit @@ -21,11 +23,18 @@ internal class ApkUpdateValues(store: KeyValueStore) : SignalStoreValues(store) var autoUpdate: Boolean by booleanValue(AUTO_UPDATE, true) var lastSuccessfulCheck: Long by longValue(LAST_SUCCESSFUL_CHECK, 0) - fun setDownloadAttributes(id: Long, digest: ByteArray?) { + /** The upload of the last APK we installed */ + var lastApkUploadTime: Long by longValue(LAST_APK_UPLOAD_TIME, 0) + + /** The upload time of the APK we're trying to install */ + val pendingApkUploadTime: Long by longValue(PENDING_APK_UPLOAD_TIME, 0) + + fun setDownloadAttributes(id: Long, digest: ByteArray?, apkUploadTime: Long) { store .beginWrite() .putLong(DOWNLOAD_ID, id) .putBlob(DIGEST, digest) + .putLong(PENDING_APK_UPLOAD_TIME, apkUploadTime) .commit() } @@ -34,6 +43,7 @@ internal class ApkUpdateValues(store: KeyValueStore) : SignalStoreValues(store) .beginWrite() .putLong(DOWNLOAD_ID, -1) .putBlob(DIGEST, null) + .putLong(PENDING_APK_UPLOAD_TIME, 0) .commit() } }