From 375815c7190444f0a4d49b304095551866ce0cd5 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Fri, 5 May 2023 16:51:44 +1000 Subject: [PATCH] WIP: refactor on jobs using old job table --- .../securesms/jobmanager/JobManager.java | 39 --- .../securesms/jobs/JobManagerFactories.java | 4 +- .../securesms/jobs/LocalBackupJob.java | 83 ------ .../securesms/jobs/LocalBackupJob.kt | 61 ++++ .../securesms/jobs/UpdateApkJob.java | 271 ------------------ .../securesms/jobs/UpdateApkJob.kt | 200 +++++++++++++ .../service/UpdateApkRefreshListener.java | 2 + .../sskenvironment/ProfileManager.kt | 1 + 8 files changed, 266 insertions(+), 395 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.java create mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.kt delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.java create mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java index 5906afd292..abb15d9f75 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java @@ -78,35 +78,6 @@ public class JobManager implements ConstraintObserver.Notifier { new Chain(this, Collections.singletonList(job)).enqueue(); } - /** - * Begins the creation of a job chain with a single job. - * @see Chain - */ - public Chain startChain(@NonNull Job job) { - return new Chain(this, Collections.singletonList(job)); - } - - /** - * Begins the creation of a job chain with a set of jobs that can be run in parallel. - * @see Chain - */ - public Chain startChain(@NonNull List jobs) { - return new Chain(this, jobs); - } - - /** - * Retrieves a string representing the state of the job queue. Intended for debugging. - */ - public @NonNull String getDebugInfo() { - Future result = executor.submit(jobController::getDebugInfo); - try { - return result.get(); - } catch (ExecutionException | InterruptedException e) { - Log.w(TAG, "Failed to retrieve Job info.", e); - return "Failed to retrieve Job info."; - } - } - /** * Adds a listener to that will be notified when the job queue has been drained. */ @@ -261,16 +232,6 @@ public class JobManager implements ConstraintObserver.Notifier { private Data.Serializer dataSerializer = new JsonDataSerializer(); private JobStorage jobStorage = null; - public @NonNull Builder setJobThreadCount(int jobThreadCount) { - this.jobThreadCount = jobThreadCount; - return this; - } - - public @NonNull Builder setExecutorFactory(@NonNull ExecutorFactory executorFactory) { - this.executorFactory = executorFactory; - return this; - } - public @NonNull Builder setJobFactories(@NonNull Map jobFactories) { this.jobFactories = jobFactories; return this; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java index ef73325f37..468bf58369 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java @@ -29,9 +29,9 @@ public final class JobManagerFactories { public static Map getJobFactories(@NonNull Application application) { HashMap factoryHashMap = new HashMap() {{ put(AvatarDownloadJob.KEY, new AvatarDownloadJob.Factory()); - put(LocalBackupJob.KEY, new LocalBackupJob.Factory()); + put(LocalBackupJob.Companion.getKEY(), new LocalBackupJob.Factory()); put(RetrieveProfileAvatarJob.KEY, new RetrieveProfileAvatarJob.Factory(application)); - put(UpdateApkJob.KEY, new UpdateApkJob.Factory()); + put(UpdateApkJob.Companion.getKEY(), new UpdateApkJob.Factory()); put(PrepareAttachmentAudioExtrasJob.KEY, new PrepareAttachmentAudioExtrasJob.Factory()); }}; factoryKeys.addAll(factoryHashMap.keySet()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.java deleted file mode 100644 index e5715db263..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - -import androidx.annotation.NonNull; - -import org.session.libsession.messaging.utilities.Data; -import org.session.libsignal.utilities.NoExternalStorageException; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.session.libsignal.utilities.Log; -import org.thoughtcrime.securesms.database.BackupFileRecord; -import org.thoughtcrime.securesms.notifications.NotificationChannels; -import org.thoughtcrime.securesms.service.GenericForegroundService; -import org.thoughtcrime.securesms.util.BackupUtil; - -import java.io.IOException; -import java.util.Collections; - -import network.loki.messenger.R; - -public class LocalBackupJob extends BaseJob { - - public static final String KEY = "LocalBackupJob"; - - private static final String TAG = LocalBackupJob.class.getSimpleName(); - - public LocalBackupJob() { - this(new Job.Parameters.Builder() - .setQueue("__LOCAL_BACKUP__") - .setMaxInstances(1) - .setMaxAttempts(3) - .build()); - } - - private LocalBackupJob(@NonNull Job.Parameters parameters) { - super(parameters); - } - - @Override - public @NonNull - Data serialize() { - return Data.EMPTY; - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public void onRun() throws NoExternalStorageException, IOException { - Log.i(TAG, "Executing backup job..."); - - GenericForegroundService.startForegroundTask(context, - context.getString(R.string.LocalBackupJob_creating_backup), - NotificationChannels.BACKUPS, - R.drawable.ic_launcher_foreground); - - // TODO: Maybe create a new backup icon like ic_signal_backup? - - try { - BackupFileRecord record = BackupUtil.createBackupFile(context); - BackupUtil.deleteAllBackupFiles(context, Collections.singletonList(record)); - - } finally { - GenericForegroundService.stopForegroundTask(context); - } - } - - @Override - public boolean onShouldRetry(@NonNull Exception e) { - return false; - } - - @Override - public void onCanceled() { - } - - public static class Factory implements Job.Factory { - @Override - public @NonNull LocalBackupJob create(@NonNull Parameters parameters, @NonNull Data data) { - return new LocalBackupJob(parameters); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.kt new file mode 100644 index 0000000000..8a71760df3 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.kt @@ -0,0 +1,61 @@ +package org.thoughtcrime.securesms.jobs + +import android.content.Context +import org.session.libsession.messaging.jobs.Job +import org.session.libsession.messaging.jobs.JobDelegate +import org.session.libsession.messaging.utilities.Data +import org.session.libsignal.utilities.Log +import org.thoughtcrime.securesms.notifications.NotificationChannels +import org.thoughtcrime.securesms.service.GenericForegroundService +import org.thoughtcrime.securesms.util.BackupUtil.createBackupFile +import org.thoughtcrime.securesms.util.BackupUtil.deleteAllBackupFiles + +import network.loki.messenger.R + + +class LocalBackupJob:Job { + override var delegate: JobDelegate? = null + override var id: String? = null + override var failureCount: Int = 0 + override val maxFailureCount: Int = 0 + + lateinit var context: Context + + companion object { + val TAG = LocalBackupJob::class.simpleName + val KEY: String = "LocalBackupJob" + } + + override fun execute(dispatcherName: String) { + Log.i(TAG, "Executing backup job...") + + GenericForegroundService.startForegroundTask( + context, + context.getString(R.string.LocalBackupJob_creating_backup), + NotificationChannels.BACKUPS, + R.drawable.ic_launcher_foreground + ) + + // TODO: Maybe create a new backup icon like ic_signal_backup? + try { + val record = createBackupFile(context) + deleteAllBackupFiles(context, listOf(record)) + } finally { + GenericForegroundService.stopForegroundTask(context) + } + } + + override fun serialize(): Data { + return Data.EMPTY + } + + override fun getFactoryKey(): String { + return KEY + } + + class Factory: Job.Factory { + override fun create(data: Data): LocalBackupJob { + return LocalBackupJob() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.java deleted file mode 100644 index 5b4ce8d13c..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.java +++ /dev/null @@ -1,271 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - - -import android.app.DownloadManager; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.database.Cursor; -import android.net.Uri; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import org.session.libsession.messaging.utilities.Data; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.session.libsignal.utilities.Log; -import org.thoughtcrime.securesms.service.UpdateApkReadyListener; -import org.session.libsession.utilities.FileUtils; -import org.session.libsignal.utilities.Hex; -import org.session.libsignal.utilities.JsonUtil; -import org.session.libsession.utilities.TextSecurePreferences; - -import java.io.FileInputStream; -import java.io.IOException; -import java.security.MessageDigest; - -import network.loki.messenger.BuildConfig; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; - -public class UpdateApkJob extends BaseJob { - - public static final String KEY = "UpdateApkJob"; - - private static final String TAG = UpdateApkJob.class.getSimpleName(); - - public UpdateApkJob() { - this(new Job.Parameters.Builder() - .setQueue("UpdateApkJob") - .addConstraint(NetworkConstraint.KEY) - .setMaxAttempts(3) - .build()); - } - - private UpdateApkJob(@NonNull Job.Parameters parameters) { - super(parameters); - } - - @Override - public @NonNull - Data serialize() { - return Data.EMPTY; - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public void onRun() throws IOException, PackageManager.NameNotFoundException { - if (!BuildConfig.PLAY_STORE_DISABLED) return; - - Log.i(TAG, "Checking for APK update..."); - - OkHttpClient client = new OkHttpClient(); - Request request = new Request.Builder().url(String.format("%s/latest.json", BuildConfig.NOPLAY_UPDATE_URL)).build(); - - Response response = client.newCall(request).execute(); - - if (!response.isSuccessful()) { - throw new IOException("Bad response: " + response.message()); - } - - UpdateDescriptor updateDescriptor = JsonUtil.fromJson(response.body().string(), UpdateDescriptor.class); - byte[] digest = Hex.fromStringCondensed(updateDescriptor.getDigest()); - - Log.i(TAG, "Got descriptor: " + updateDescriptor); - - if (updateDescriptor.getVersionCode() > getVersionCode()) { - DownloadStatus downloadStatus = getDownloadStatus(updateDescriptor.getUrl(), digest); - - Log.i(TAG, "Download status: " + downloadStatus.getStatus()); - - if (downloadStatus.getStatus() == DownloadStatus.Status.COMPLETE) { - Log.i(TAG, "Download status complete, notifying..."); - handleDownloadNotify(downloadStatus.getDownloadId()); - } else if (downloadStatus.getStatus() == DownloadStatus.Status.MISSING) { - Log.i(TAG, "Download status missing, starting download..."); - handleDownloadStart(updateDescriptor.getUrl(), updateDescriptor.getVersionName(), digest); - } - } - } - - @Override - public boolean onShouldRetry(@NonNull Exception e) { - return e instanceof IOException; - } - - @Override - public void onCanceled() { - Log.w(TAG, "Update check failed"); - } - - private int getVersionCode() throws PackageManager.NameNotFoundException { - PackageManager packageManager = context.getPackageManager(); - PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0); - - return packageInfo.versionCode; - } - - private DownloadStatus getDownloadStatus(String uri, byte[] theirDigest) { - DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - DownloadManager.Query query = new DownloadManager.Query(); - - query.setFilterByStatus(DownloadManager.STATUS_PAUSED | DownloadManager.STATUS_PENDING | DownloadManager.STATUS_RUNNING | DownloadManager.STATUS_SUCCESSFUL); - - long pendingDownloadId = TextSecurePreferences.getUpdateApkDownloadId(context); - byte[] pendingDigest = getPendingDigest(context); - Cursor cursor = downloadManager.query(query); - - try { - DownloadStatus status = new DownloadStatus(DownloadStatus.Status.MISSING, -1); - - while (cursor != null && cursor.moveToNext()) { - int jobStatus = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS)); - String jobRemoteUri = cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_URI)); - long downloadId = cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID)); - byte[] digest = getDigestForDownloadId(downloadId); - - if (jobRemoteUri != null && jobRemoteUri.equals(uri) && downloadId == pendingDownloadId) { - - if (jobStatus == DownloadManager.STATUS_SUCCESSFUL && - digest != null && pendingDigest != null && - MessageDigest.isEqual(pendingDigest, theirDigest) && - MessageDigest.isEqual(digest, theirDigest)) - { - return new DownloadStatus(DownloadStatus.Status.COMPLETE, downloadId); - } else if (jobStatus != DownloadManager.STATUS_SUCCESSFUL) { - status = new DownloadStatus(DownloadStatus.Status.PENDING, downloadId); - } - } - } - - return status; - } finally { - if (cursor != null) cursor.close(); - } - } - - private void handleDownloadStart(String uri, String versionName, byte[] digest) { - DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(uri)); - - downloadRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI); - downloadRequest.setTitle("Downloading Signal update"); - downloadRequest.setDescription("Downloading Signal " + versionName); - downloadRequest.setVisibleInDownloadsUi(false); - downloadRequest.setDestinationInExternalFilesDir(context, null, "signal-update.apk"); - downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN); - - long downloadId = downloadManager.enqueue(downloadRequest); - TextSecurePreferences.setUpdateApkDownloadId(context, downloadId); - TextSecurePreferences.setUpdateApkDigest(context, Hex.toStringCondensed(digest)); - } - - private void handleDownloadNotify(long downloadId) { - Intent intent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE); - intent.putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, downloadId); - - new UpdateApkReadyListener().onReceive(context, intent); - } - - private @Nullable byte[] getDigestForDownloadId(long downloadId) { - try { - DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - FileInputStream fin = new FileInputStream(downloadManager.openDownloadedFile(downloadId).getFileDescriptor()); - byte[] digest = FileUtils.getFileDigest(fin); - - fin.close(); - - return digest; - } catch (IOException e) { - Log.w(TAG, e); - return null; - } - } - - private @Nullable byte[] getPendingDigest(Context context) { - try { - String encodedDigest = TextSecurePreferences.getUpdateApkDigest(context); - - if (encodedDigest == null) return null; - - return Hex.fromStringCondensed(encodedDigest); - } catch (IOException e) { - Log.w(TAG, e); - return null; - } - } - - private static class UpdateDescriptor { - @JsonProperty - private int versionCode; - - @JsonProperty - private String versionName; - - @JsonProperty - private String url; - - @JsonProperty - private String sha256sum; - - - public int getVersionCode() { - return versionCode; - } - - public String getVersionName() { - return versionName; - } - - public String getUrl() { - return url; - } - - public @NonNull String toString() { - return "[" + versionCode + ", " + versionName + ", " + url + "]"; - } - - public String getDigest() { - return sha256sum; - } - } - - private static class DownloadStatus { - enum Status { - PENDING, - COMPLETE, - MISSING - } - - private final Status status; - private final long downloadId; - - DownloadStatus(Status status, long downloadId) { - this.status = status; - this.downloadId = downloadId; - } - - public Status getStatus() { - return status; - } - - public long getDownloadId() { - return downloadId; - } - } - - public static final class Factory implements Job.Factory { - @Override - public @NonNull UpdateApkJob create(@NonNull Parameters parameters, @NonNull Data data) { - return new UpdateApkJob(parameters); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.kt new file mode 100644 index 0000000000..411f01fcde --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.kt @@ -0,0 +1,200 @@ +package org.thoughtcrime.securesms.jobs + +import androidx.annotation.Nullable + +import android.app.DownloadManager +import android.content.Context +import android.content.Intent +import android.content.pm.PackageInfo +import android.content.pm.PackageManager +import android.net.Uri +import com.fasterxml.jackson.annotation.JsonProperty +import network.loki.messenger.BuildConfig +import okhttp3.OkHttpClient +import okhttp3.Request +import org.session.libsession.messaging.jobs.Job +import org.session.libsession.messaging.jobs.JobDelegate +import org.session.libsession.messaging.utilities.Data +import org.session.libsession.utilities.FileUtils +import org.session.libsession.utilities.TextSecurePreferences.Companion.getUpdateApkDigest +import org.session.libsession.utilities.TextSecurePreferences.Companion.getUpdateApkDownloadId +import org.session.libsession.utilities.TextSecurePreferences.Companion.setUpdateApkDigest +import org.session.libsession.utilities.TextSecurePreferences.Companion.setUpdateApkDownloadId +import org.session.libsignal.utilities.Hex +import org.session.libsignal.utilities.JsonUtil +import org.session.libsignal.utilities.Log +import org.thoughtcrime.securesms.service.UpdateApkReadyListener +import java.io.FileInputStream +import java.io.IOException +import java.security.MessageDigest + +class UpdateApkJob: Job { + override var delegate: JobDelegate? = null + override var id: String? = null + override var failureCount: Int = 0 + override val maxFailureCount: Int = 0 + + lateinit var context: Context + + companion object { + val TAG = UpdateApkJob::class.simpleName + val KEY: String = "UpdateApkJob" + } + + override fun execute(dispatcherName: String) { + if (!BuildConfig.PLAY_STORE_DISABLED) return + + Log.i(TAG, "Checking for APK update...") + + val client = OkHttpClient() + val request = Request.Builder().url(String.format("%s/latest.json", BuildConfig.NOPLAY_UPDATE_URL)).build() + val response = client.newCall(request).execute() + + if (!response.isSuccessful) { + throw IOException("Bad response: " + response.message()) + } + + val updateDescriptor: UpdateDescriptor = JsonUtil.fromJson( + response.body()!!.string(), + UpdateDescriptor::class.java + ) + val digest = Hex.fromStringCondensed(updateDescriptor.digest) + + Log.i( + TAG, + "Got descriptor: $updateDescriptor" + ) + + if (updateDescriptor.versionCode > getVersionCode()) { + val downloadStatus: DownloadStatus = getDownloadStatus(updateDescriptor.url, digest) + Log.i(TAG, "Download status: " + downloadStatus.status) + if (downloadStatus.status == DownloadStatus.Status.COMPLETE) { + Log.i(TAG, "Download status complete, notifying...") + handleDownloadNotify(downloadStatus.downloadId) + } else if (downloadStatus.status == DownloadStatus.Status.MISSING) { + Log.i(TAG, "Download status missing, starting download...") + handleDownloadStart( + updateDescriptor.url, + updateDescriptor.versionName, + digest + ) + } + } + } + + @Throws(PackageManager.NameNotFoundException::class) + private fun getVersionCode(): Int { + val packageManager: PackageManager = context.getPackageManager() + val packageInfo: PackageInfo = packageManager.getPackageInfo(context.getPackageName(), 0) + return packageInfo.versionCode + } + + private fun getDownloadStatus(uri: String, theirDigest: ByteArray): DownloadStatus { + val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager + val query = DownloadManager.Query() + query.setFilterByStatus(DownloadManager.STATUS_PAUSED or DownloadManager.STATUS_PENDING or DownloadManager.STATUS_RUNNING or DownloadManager.STATUS_SUCCESSFUL) + val pendingDownloadId = getUpdateApkDownloadId(context) + val pendingDigest = getPendingDigest(context) + val cursor = downloadManager.query(query) + return try { + var status = DownloadStatus(DownloadStatus.Status.MISSING, -1) + while (cursor != null && cursor.moveToNext()) { + val jobStatus = + cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS)) + val jobRemoteUri = + cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_URI)) + val downloadId = + cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID)) + val digest = getDigestForDownloadId(downloadId) + if (jobRemoteUri != null && jobRemoteUri == uri && downloadId == pendingDownloadId) { + if (jobStatus == DownloadManager.STATUS_SUCCESSFUL && digest != null && pendingDigest != null && + MessageDigest.isEqual(pendingDigest, theirDigest) && + MessageDigest.isEqual(digest, theirDigest) + ) { + return DownloadStatus(DownloadStatus.Status.COMPLETE, downloadId) + } else if (jobStatus != DownloadManager.STATUS_SUCCESSFUL) { + status = DownloadStatus(DownloadStatus.Status.PENDING, downloadId) + } + } + } + status + } finally { + cursor?.close() + } + } + + private fun handleDownloadStart(uri: String, versionName: String, digest: ByteArray) { + val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager + val downloadRequest = DownloadManager.Request(Uri.parse(uri)) + downloadRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI) + downloadRequest.setTitle("Downloading Signal update") + downloadRequest.setDescription("Downloading Signal $versionName") + downloadRequest.setVisibleInDownloadsUi(false) + downloadRequest.setDestinationInExternalFilesDir(context, null, "signal-update.apk") + downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN) + val downloadId = downloadManager.enqueue(downloadRequest) + setUpdateApkDownloadId(context, downloadId) + setUpdateApkDigest(context, Hex.toStringCondensed(digest)) + } + + private fun handleDownloadNotify(downloadId: Long) { + val intent = Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE) + intent.putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, downloadId) + UpdateApkReadyListener().onReceive(context, intent) + } + + private fun getDigestForDownloadId(downloadId: Long): ByteArray? { + return try { + val downloadManager = + context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager + val fin = FileInputStream(downloadManager.openDownloadedFile(downloadId).fileDescriptor) + val digest = FileUtils.getFileDigest(fin) + fin.close() + digest + } catch (e: IOException) { + Log.w(TAG, e) + null + } + } + + private fun getPendingDigest(context: Context): ByteArray? { + return try { + val encodedDigest = getUpdateApkDigest(context) ?: return null + Hex.fromStringCondensed(encodedDigest) + } catch (e: IOException) { + Log.w(TAG, e) + null + } + } + + override fun serialize(): Data { + return Data.EMPTY + } + + override fun getFactoryKey(): String { + return KEY + } + + private class UpdateDescriptor( + @JsonProperty("versionCode") @Nullable val versionCode: Int, + @JsonProperty("versionName") @Nullable val versionName: String, + @JsonProperty("url") @Nullable val url: String, + @JsonProperty("sha256sum") @Nullable val digest: String) + { + override fun toString(): String { + return "[$versionCode, $versionName, $url]" + } + } + + private class DownloadStatus(val status: Status, val downloadId: Long) { + enum class Status { + PENDING, COMPLETE, MISSING + } + } + + class Factory: Job.Factory { + override fun create(data: Data): UpdateApkJob { + return UpdateApkJob() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java b/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java index 187713df95..ef27916ac9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java @@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.service; import android.content.Context; import android.content.Intent; + +import org.session.libsession.messaging.jobs.JobQueue; import org.session.libsignal.utilities.Log; import org.thoughtcrime.securesms.ApplicationContext; diff --git a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt index c46f75bff8..2615eff588 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.sskenvironment import android.content.Context import org.session.libsession.messaging.contacts.Contact +import org.session.libsession.messaging.jobs.JobQueue import org.session.libsession.utilities.SSKEnvironment import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.ApplicationContext