From 42f1baaf61ca1edd911a37de237dc86011a7ae87 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Mon, 18 Jun 2018 12:27:04 -0700 Subject: [PATCH] Imported JobManager as a source dependency. We have to make some changes, and it's gotten to the point where maintaining it as a separate library is more hassle than it's worth, especially with Google releasing WorkManager as the preferred job scheduling library. --- build.gradle | 2 - .../securesms/ApplicationContext.java | 8 +- .../securesms/ConversationListFragment.java | 1 - .../components/camera/CameraView.java | 18 +- .../securesms/database/MmsDatabase.java | 5 +- .../securesms/database/SmsDatabase.java | 2 +- .../securesms/jobmanager/EncryptionKeys.java | 30 + .../securesms/jobmanager/Job.java | 135 ++++ .../securesms/jobmanager/JobConsumer.java | 94 +++ .../securesms/jobmanager/JobManager.java | 252 ++++++ .../securesms/jobmanager/JobParameters.java | 190 +++++ .../securesms/jobmanager/JobQueue.java | 95 +++ .../AggregateDependencyInjector.java | 36 + .../dependencies/ContextDependent.java | 27 + .../dependencies/DependencyInjector.java | 24 + .../persistence/JavaJobSerializer.java | 66 ++ .../jobmanager/persistence/JobSerializer.java | 47 ++ .../persistence/PersistentStorage.java | 134 ++++ .../requirements/NetworkRequirement.java | 50 ++ .../NetworkRequirementProvider.java | 53 ++ .../jobmanager/requirements/Requirement.java | 29 + .../requirements/RequirementListener.java | 21 + .../requirements/RequirementProvider.java | 33 + .../securesms/jobmanager/util/Base64.java | 741 ++++++++++++++++++ .../securesms/jobs/AttachmentDownloadJob.java | 4 +- .../securesms/jobs/AttachmentFileNameJob.java | 2 +- .../securesms/jobs/AvatarDownloadJob.java | 4 +- .../securesms/jobs/CleanPreKeysJob.java | 2 +- .../securesms/jobs/ContextJob.java | 6 +- .../securesms/jobs/CreateSignedPreKeyJob.java | 4 +- .../securesms/jobs/DirectoryRefreshJob.java | 4 +- .../securesms/jobs/GcmRefreshJob.java | 4 +- .../securesms/jobs/LocalBackupJob.java | 2 +- .../securesms/jobs/MasterSecretJob.java | 2 +- .../securesms/jobs/MmsDownloadJob.java | 4 +- .../securesms/jobs/MmsReceiveJob.java | 2 +- .../securesms/jobs/MmsSendJob.java | 4 +- .../jobs/MultiDeviceBlockedUpdateJob.java | 4 +- .../jobs/MultiDeviceContactUpdateJob.java | 4 +- .../jobs/MultiDeviceGroupUpdateJob.java | 4 +- .../jobs/MultiDeviceProfileKeyUpdateJob.java | 4 +- .../jobs/MultiDeviceReadReceiptUpdateJob.java | 4 +- .../jobs/MultiDeviceReadUpdateJob.java | 4 +- .../jobs/MultiDeviceVerifiedUpdateJob.java | 4 +- .../securesms/jobs/PushContentReceiveJob.java | 2 +- .../securesms/jobs/PushDecryptJob.java | 2 +- .../securesms/jobs/PushGroupSendJob.java | 4 +- .../securesms/jobs/PushGroupUpdateJob.java | 4 +- .../jobs/PushNotificationReceiveJob.java | 4 +- .../securesms/jobs/PushReceivedJob.java | 4 +- .../securesms/jobs/PushSendJob.java | 4 +- .../securesms/jobs/RefreshAttributesJob.java | 4 +- .../securesms/jobs/RefreshPreKeysJob.java | 4 +- .../securesms/jobs/RequestGroupInfoJob.java | 4 +- .../jobs/RetrieveProfileAvatarJob.java | 4 +- .../securesms/jobs/RetrieveProfileJob.java | 4 +- .../securesms/jobs/RotateSignedPreKeyJob.java | 4 +- .../thoughtcrime/securesms/jobs/SendJob.java | 2 +- .../securesms/jobs/SendReadReceiptJob.java | 4 +- .../jobs/ServiceOutageDetectionJob.java | 4 +- .../securesms/jobs/SmsReceiveJob.java | 3 +- .../securesms/jobs/SmsSendJob.java | 2 +- .../securesms/jobs/SmsSentJob.java | 2 +- .../securesms/jobs/TrimThreadJob.java | 4 +- .../securesms/jobs/UpdateApkJob.java | 4 +- .../requirements/MasterSecretRequirement.java | 4 +- .../MasterSecretRequirementProvider.java | 4 +- .../NetworkOrServiceRequirement.java | 6 +- .../jobs/requirements/ServiceRequirement.java | 11 +- .../ServiceRequirementProvider.java | 4 +- .../SqlCipherMigrationRequirement.java | 4 +- ...SqlCipherMigrationRequirementProvider.java | 4 +- .../service/MessageRetrievalService.java | 6 +- .../service/SmsDeliveryListener.java | 2 +- .../securesms/sms/MessageSender.java | 2 +- 75 files changed, 2165 insertions(+), 120 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/jobmanager/EncryptionKeys.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/Job.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/JobConsumer.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/JobManager.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/JobParameters.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/JobQueue.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/dependencies/AggregateDependencyInjector.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/dependencies/ContextDependent.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/dependencies/DependencyInjector.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/persistence/JavaJobSerializer.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/persistence/JobSerializer.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/persistence/PersistentStorage.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirement.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirementProvider.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/requirements/Requirement.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementListener.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementProvider.java create mode 100644 src/org/thoughtcrime/securesms/jobmanager/util/Base64.java diff --git a/build.gradle b/build.gradle index d0b6925e3f..230923b15d 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,6 @@ dependencies { compile 'com.google.android.exoplayer:exoplayer:r2.3.1' - compile 'org.whispersystems:jobmanager:1.0.2' compile('org.whispersystems:libpastelog:1.1.2') { exclude group: 'com.squareup.okhttp3', module: 'okhttp' } @@ -174,7 +173,6 @@ dependencyVerification { 'com.google.android.gms:play-services-places:abf3a4a3b146ec7e6e753be62775e512868cf37d6f88ffe2d81167b33b57132b', 'com.google.android.gms:play-services-maps:45e8021e7ddac4a44a82a0e9698991389ded3023d35c58f38dbd86d54211ec0e', 'com.google.android.exoplayer:exoplayer:955085aa611a8f7cf6c61b88ae03d1a392f4ad94c9bfbc153f3dedb9ffb14718', - 'org.whispersystems:jobmanager:506f679fc2fcf7bb6d10f00f41d6f6ea0abf75c70dc95b913398661ad538a181', 'org.whispersystems:libpastelog:fe56b4db9ec743c8b565e3e4caa9228fafe132dc0bf82000d6e359b97a81177c', 'org.whispersystems:signal-service-android:823eed29e64fb0aa30d2078cb5ec0245e2a0713a4028121329c5c28788ef27f8', 'org.whispersystems:webrtc-android:ed297e8b795dad9658cf306c2aa0f7d296c65f0997a2ac4353fd0157910acc12', diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index 5c3301c98c..5f9ec4941b 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -29,6 +29,10 @@ import org.thoughtcrime.securesms.crypto.PRNGFixes; import org.thoughtcrime.securesms.dependencies.AxolotlStorageModule; import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule; +import org.thoughtcrime.securesms.jobmanager.JobManager; +import org.thoughtcrime.securesms.jobmanager.dependencies.DependencyInjector; +import org.thoughtcrime.securesms.jobmanager.persistence.JavaJobSerializer; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirementProvider; import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob; import org.thoughtcrime.securesms.jobs.GcmRefreshJob; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirementProvider; @@ -45,10 +49,6 @@ import org.webrtc.PeerConnectionFactory; import org.webrtc.PeerConnectionFactory.InitializationOptions; import org.webrtc.voiceengine.WebRtcAudioManager; import org.webrtc.voiceengine.WebRtcAudioUtils; -import org.whispersystems.jobqueue.JobManager; -import org.whispersystems.jobqueue.dependencies.DependencyInjector; -import org.whispersystems.jobqueue.persistence.JavaJobSerializer; -import org.whispersystems.jobqueue.requirements.NetworkRequirementProvider; import org.whispersystems.libsignal.logging.SignalProtocolLoggerProvider; import org.whispersystems.libsignal.util.AndroidSignalProtocolLogger; diff --git a/src/org/thoughtcrime/securesms/ConversationListFragment.java b/src/org/thoughtcrime/securesms/ConversationListFragment.java index 4e3c1b5d1f..35f93992b7 100644 --- a/src/org/thoughtcrime/securesms/ConversationListFragment.java +++ b/src/org/thoughtcrime/securesms/ConversationListFragment.java @@ -82,7 +82,6 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.task.SnackbarAsyncTask; -import org.whispersystems.jobqueue.JobManager; import org.whispersystems.libsignal.util.guava.Optional; import java.util.HashSet; diff --git a/src/org/thoughtcrime/securesms/components/camera/CameraView.java b/src/org/thoughtcrime/securesms/components/camera/CameraView.java index 4eb56a18d2..de84e3fbd0 100644 --- a/src/org/thoughtcrime/securesms/components/camera/CameraView.java +++ b/src/org/thoughtcrime/securesms/components/camera/CameraView.java @@ -36,20 +36,20 @@ import android.util.Log; import android.view.OrientationEventListener; import android.view.ViewGroup; +import org.thoughtcrime.securesms.ApplicationContext; +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.jobmanager.Job; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.util.BitmapUtil; +import org.thoughtcrime.securesms.util.TextSecurePreferences; +import org.thoughtcrime.securesms.util.Util; +import org.whispersystems.libsignal.util.guava.Optional; + import java.io.IOException; import java.util.Collections; import java.util.LinkedList; import java.util.List; -import org.thoughtcrime.securesms.ApplicationContext; -import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.util.BitmapUtil; -import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.thoughtcrime.securesms.util.Util; -import org.whispersystems.jobqueue.Job; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.libsignal.util.guava.Optional; - @SuppressWarnings("deprecation") public class CameraView extends ViewGroup { private static final String TAG = CameraView.class.getSimpleName(); diff --git a/src/org/thoughtcrime/securesms/database/MmsDatabase.java b/src/org/thoughtcrime/securesms/database/MmsDatabase.java index 36c5fc5e7b..2c5a0fc44d 100644 --- a/src/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -50,6 +50,7 @@ import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord; import org.thoughtcrime.securesms.database.model.Quote; +import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobs.TrimThreadJob; import org.thoughtcrime.securesms.mms.IncomingMediaMessage; import org.thoughtcrime.securesms.mms.MmsException; @@ -64,7 +65,6 @@ import org.thoughtcrime.securesms.recipients.RecipientFormattingException; import org.thoughtcrime.securesms.util.JsonUtils; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; -import org.whispersystems.jobqueue.JobManager; import org.whispersystems.libsignal.util.guava.Optional; import java.io.IOException; @@ -78,7 +78,8 @@ import java.util.List; import java.util.Map; import java.util.Set; -import static org.thoughtcrime.securesms.contactshare.Contact.*; +import static org.thoughtcrime.securesms.contactshare.Contact.Avatar; +import static org.thoughtcrime.securesms.contactshare.Contact.deserialize; public class MmsDatabase extends MessagingDatabase { diff --git a/src/org/thoughtcrime/securesms/database/SmsDatabase.java b/src/org/thoughtcrime/securesms/database/SmsDatabase.java index 2b926e74fd..a311e89a52 100644 --- a/src/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -36,6 +36,7 @@ import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchList; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.SmsMessageRecord; +import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobs.TrimThreadJob; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.sms.IncomingGroupMessage; @@ -43,7 +44,6 @@ import org.thoughtcrime.securesms.sms.IncomingTextMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.thoughtcrime.securesms.util.JsonUtils; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobManager; import org.whispersystems.libsignal.util.guava.Optional; import java.io.IOException; diff --git a/src/org/thoughtcrime/securesms/jobmanager/EncryptionKeys.java b/src/org/thoughtcrime/securesms/jobmanager/EncryptionKeys.java new file mode 100644 index 0000000000..588c6ca366 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/EncryptionKeys.java @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager; + +public class EncryptionKeys { + + private transient final byte[] encoded; + + public EncryptionKeys(byte[] encoded) { + this.encoded = encoded; + } + + public byte[] getEncoded() { + return encoded; + } +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/Job.java b/src/org/thoughtcrime/securesms/jobmanager/Job.java new file mode 100644 index 0000000000..bde2b54571 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/Job.java @@ -0,0 +1,135 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager; + +import android.os.PowerManager; + +import org.thoughtcrime.securesms.jobmanager.requirements.Requirement; + +import java.io.Serializable; +import java.util.List; + +/** + * An abstract class representing a unit of work that can be scheduled with + * the JobManager. This should be extended to implement tasks. + */ +public abstract class Job implements Serializable { + + private final JobParameters parameters; + + private transient long persistentId; + private transient int runIteration; + private transient PowerManager.WakeLock wakeLock; + + public Job(JobParameters parameters) { + this.parameters = parameters; + } + + public List getRequirements() { + return parameters.getRequirements(); + } + + public boolean isRequirementsMet() { + for (Requirement requirement : parameters.getRequirements()) { + if (!requirement.isPresent()) return false; + } + + return true; + } + + public String getGroupId() { + return parameters.getGroupId(); + } + + public boolean isPersistent() { + return parameters.isPersistent(); + } + + public EncryptionKeys getEncryptionKeys() { + return parameters.getEncryptionKeys(); + } + + public void setEncryptionKeys(EncryptionKeys keys) { + parameters.setEncryptionKeys(keys); + } + + public int getRetryCount() { + return parameters.getRetryCount(); + } + + public void setPersistentId(long persistentId) { + this.persistentId = persistentId; + } + + public long getPersistentId() { + return persistentId; + } + + public int getRunIteration() { + return runIteration; + } + + public void setRunIteration(int runIteration) { + this.runIteration = runIteration; + } + + public boolean needsWakeLock() { + return parameters.needsWakeLock(); + } + + public long getWakeLockTimeout() { + return parameters.getWakeLockTimeout(); + } + + public void setWakeLock(PowerManager.WakeLock wakeLock) { + this.wakeLock = wakeLock; + } + + public PowerManager.WakeLock getWakeLock() { + return this.wakeLock; + } + + /** + * Called after a job has been added to the JobManager queue. If it's a persistent job, + * the state has been persisted to disk before this method is called. + */ + public abstract void onAdded(); + + /** + * Called to actually execute the job. + * @throws Exception + */ + public abstract void onRun() throws Exception; + + /** + * If onRun() throws an exception, this method will be called to determine whether the + * job should be retried. + * + * @param exception The exception onRun() threw. + * @return true if onRun() should be called again, false otherwise. + */ + public abstract boolean onShouldRetry(Exception exception); + + /** + * Called if a job fails to run (onShouldRetry returned false, or the number of retries exceeded + * the job's configured retry count. + */ + public abstract void onCanceled(); + + + +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/JobConsumer.java b/src/org/thoughtcrime/securesms/jobmanager/JobConsumer.java new file mode 100644 index 0000000000..b4e4a9aeec --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/JobConsumer.java @@ -0,0 +1,94 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager; + +import android.util.Log; + +import org.thoughtcrime.securesms.jobmanager.persistence.PersistentStorage; + +class JobConsumer extends Thread { + + private static final String TAG = JobConsumer.class.getSimpleName(); + + enum JobResult { + SUCCESS, + FAILURE, + DEFERRED + } + + private final JobQueue jobQueue; + private final PersistentStorage persistentStorage; + + public JobConsumer(String name, JobQueue jobQueue, PersistentStorage persistentStorage) { + super(name); + this.jobQueue = jobQueue; + this.persistentStorage = persistentStorage; + } + + @Override + public void run() { + while (true) { + Job job = jobQueue.getNext(); + JobResult result = runJob(job); + + if (result == JobResult.DEFERRED) { + jobQueue.push(job); + } else { + if (result == JobResult.FAILURE) { + job.onCanceled(); + } + + if (job.isPersistent()) { + persistentStorage.remove(job.getPersistentId()); + } + + if (job.getWakeLock() != null && job.getWakeLockTimeout() == 0) { + job.getWakeLock().release(); + } + } + + if (job.getGroupId() != null) { + jobQueue.setGroupIdAvailable(job.getGroupId()); + } + } + } + + private JobResult runJob(Job job) { + int retryCount = job.getRetryCount(); + int runIteration = job.getRunIteration(); + + for (;runIteration. + */ +package org.thoughtcrime.securesms.jobmanager; + +import android.content.Context; +import android.os.PowerManager; +import android.util.Log; + +import org.thoughtcrime.securesms.jobmanager.dependencies.AggregateDependencyInjector; +import org.thoughtcrime.securesms.jobmanager.dependencies.DependencyInjector; +import org.thoughtcrime.securesms.jobmanager.persistence.JobSerializer; +import org.thoughtcrime.securesms.jobmanager.persistence.PersistentStorage; +import org.thoughtcrime.securesms.jobmanager.requirements.RequirementListener; +import org.thoughtcrime.securesms.jobmanager.requirements.RequirementProvider; + +import java.io.IOException; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * A JobManager allows you to enqueue {@link org.thoughtcrime.securesms.jobmanager.Job} tasks + * that are executed once a Job's {@link org.thoughtcrime.securesms.jobmanager.requirements.Requirement}s + * are met. + */ +public class JobManager implements RequirementListener { + + private final JobQueue jobQueue = new JobQueue(); + private final Executor eventExecutor = Executors.newSingleThreadExecutor(); + private final AtomicBoolean hasLoadedEncrypted = new AtomicBoolean(false); + + private final Context context; + private final PersistentStorage persistentStorage; + private final List requirementProviders; + private final AggregateDependencyInjector dependencyInjector; + + private JobManager(Context context, String name, + List requirementProviders, + DependencyInjector dependencyInjector, + JobSerializer jobSerializer, int consumers) + { + this.context = context; + this.dependencyInjector = new AggregateDependencyInjector(dependencyInjector); + this.persistentStorage = new PersistentStorage(context, name, jobSerializer, this.dependencyInjector); + this.requirementProviders = requirementProviders; + + eventExecutor.execute(new LoadTask(null)); + + if (requirementProviders != null && !requirementProviders.isEmpty()) { + for (RequirementProvider provider : requirementProviders) { + provider.setListener(this); + } + } + + for (int i=0;i pendingJobs; + + if (keys == null) pendingJobs = persistentStorage.getAllUnencrypted(); + else pendingJobs = persistentStorage.getAllEncrypted(keys); + + jobQueue.addAll(pendingJobs); + } + } + + public static class Builder { + private final Context context; + private String name; + private List requirementProviders; + private DependencyInjector dependencyInjector; + private JobSerializer jobSerializer; + private int consumerThreads; + + Builder(Context context) { + this.context = context; + this.consumerThreads = 5; + } + + /** + * A name for the {@link org.thoughtcrime.securesms.jobmanager.JobManager}. This is a required parameter, + * and is linked to the durable queue used by persistent jobs. + * + * @param name The name for the JobManager to build. + * @return The builder. + */ + public Builder withName(String name) { + this.name = name; + return this; + } + + /** + * The {@link org.thoughtcrime.securesms.jobmanager.requirements.RequirementProvider}s to register with this + * JobManager. Optional. Each {@link org.thoughtcrime.securesms.jobmanager.requirements.Requirement} an + * enqueued Job depends on should have a matching RequirementProvider registered here. + * + * @param requirementProviders The RequirementProviders + * @return The builder. + */ + public Builder withRequirementProviders(RequirementProvider... requirementProviders) { + this.requirementProviders = Arrays.asList(requirementProviders); + return this; + } + + /** + * The {@link org.thoughtcrime.securesms.jobmanager.dependencies.DependencyInjector} to use for injecting + * dependencies into {@link Job}s. Optional. Injection occurs just before a Job's onAdded() callback, or + * after deserializing a persistent job. + * + * @param dependencyInjector The injector to use. + * @return The builder. + */ + public Builder withDependencyInjector(DependencyInjector dependencyInjector) { + this.dependencyInjector = dependencyInjector; + return this; + } + + /** + * The {@link org.thoughtcrime.securesms.jobmanager.persistence.JobSerializer} to use for persistent Jobs. + * Required if persistent Jobs are used. + * + * @param jobSerializer The serializer to use. + * @return The builder. + */ + public Builder withJobSerializer(JobSerializer jobSerializer) { + this.jobSerializer = jobSerializer; + return this; + } + + /** + * Set the number of threads dedicated to consuming Jobs from the queue and executing them. + * + * @param consumerThreads The number of threads. + * @return The builder. + */ + public Builder withConsumerThreads(int consumerThreads) { + this.consumerThreads = consumerThreads; + return this; + } + + /** + * @return A constructed JobManager. + */ + public JobManager build() { + if (name == null) { + throw new IllegalArgumentException("You must specify a name!"); + } + + if (requirementProviders == null) { + requirementProviders = new LinkedList<>(); + } + + return new JobManager(context, name, requirementProviders, + dependencyInjector, jobSerializer, + consumerThreads); + } + } + +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/JobParameters.java b/src/org/thoughtcrime/securesms/jobmanager/JobParameters.java new file mode 100644 index 0000000000..3873c721a8 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/JobParameters.java @@ -0,0 +1,190 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager; + +import org.thoughtcrime.securesms.jobmanager.requirements.Requirement; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * The set of parameters that describe a {@link org.thoughtcrime.securesms.jobmanager.Job}. + */ +public class JobParameters implements Serializable { + + private transient EncryptionKeys encryptionKeys; + + private final List requirements; + private final boolean isPersistent; + private final int retryCount; + private final String groupId; + private final boolean wakeLock; + private final long wakeLockTimeout; + + private JobParameters(List requirements, + boolean isPersistent, String groupId, + EncryptionKeys encryptionKeys, + int retryCount, boolean wakeLock, + long wakeLockTimeout) + { + this.requirements = requirements; + this.isPersistent = isPersistent; + this.groupId = groupId; + this.encryptionKeys = encryptionKeys; + this.retryCount = retryCount; + this.wakeLock = wakeLock; + this.wakeLockTimeout = wakeLockTimeout; + } + + public List getRequirements() { + return requirements; + } + + public boolean isPersistent() { + return isPersistent; + } + + public EncryptionKeys getEncryptionKeys() { + return encryptionKeys; + } + + public void setEncryptionKeys(EncryptionKeys encryptionKeys) { + this.encryptionKeys = encryptionKeys; + } + + public int getRetryCount() { + return retryCount; + } + + /** + * @return a builder used to construct JobParameters. + */ + public static Builder newBuilder() { + return new Builder(); + } + + public String getGroupId() { + return groupId; + } + + public boolean needsWakeLock() { + return wakeLock; + } + + public long getWakeLockTimeout() { + return wakeLockTimeout; + } + + public static class Builder { + private List requirements = new LinkedList<>(); + private boolean isPersistent = false; + private EncryptionKeys encryptionKeys = null; + private int retryCount = 100; + private String groupId = null; + private boolean wakeLock = false; + private long wakeLockTimeout = 0; + + /** + * Specify a {@link org.thoughtcrime.securesms.jobmanager.requirements.Requirement }that must be met + * before the Job is executed. May be called multiple times to register multiple requirements. + * @param requirement The Requirement that must be met. + * @return the builder. + */ + public Builder withRequirement(Requirement requirement) { + this.requirements.add(requirement); + return this; + } + + /** + * Specify that the Job should be durably persisted to disk, so that it remains in the queue + * across application restarts. + * @return The builder. + */ + public Builder withPersistence() { + this.isPersistent = true; + return this; + } + + /** + * Specify that the job should use encryption when durably persisted to disk. + * @param encryptionKeys The keys to encrypt the serialized job with before persisting. + * @return the builder. + */ + public Builder withEncryption(EncryptionKeys encryptionKeys) { + this.encryptionKeys = encryptionKeys; + return this; + } + + /** + * Specify how many times the job should be retried if execution fails but onShouldRetry() returns + * true. + * + * @param retryCount The number of times the job should be retried. + * @return the builder. + */ + public Builder withRetryCount(int retryCount) { + this.retryCount = retryCount; + return this; + } + + /** + * Specify a groupId the job should belong to. Jobs with the same groupId are guaranteed to be + * executed serially. + * + * @param groupId The job's groupId. + * @return the builder. + */ + public Builder withGroupId(String groupId) { + this.groupId = groupId; + return this; + } + + /** + * Specify whether this job should hold a wake lock. + * + * @param needsWakeLock If set, this job will acquire a wakelock on add(), and hold it until + * run() completes, or cancel(). + * @param timeout Specify a timeout for the wakelock. A timeout of + * 0 will result in no timeout. + * + * @return the builder. + */ + public Builder withWakeLock(boolean needsWakeLock, long timeout, TimeUnit unit) { + this.wakeLock = needsWakeLock; + this.wakeLockTimeout = unit.toMillis(timeout); + return this; + } + + /** + * Specify whether this job should hold a wake lock. + * + * @return the builder. + */ + public Builder withWakeLock(boolean needsWakeLock) { + return withWakeLock(needsWakeLock, 0, TimeUnit.MILLISECONDS); + } + + /** + * @return the JobParameters instance that describes a Job. + */ + public JobParameters create() { + return new JobParameters(requirements, isPersistent, groupId, encryptionKeys, retryCount, wakeLock, wakeLockTimeout); + } + } +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/JobQueue.java b/src/org/thoughtcrime/securesms/jobmanager/JobQueue.java new file mode 100644 index 0000000000..246b3242fa --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/JobQueue.java @@ -0,0 +1,95 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Set; + +class JobQueue { + + private final Set activeGroupIds = new HashSet<>(); + private final LinkedList jobQueue = new LinkedList<>(); + + synchronized void onRequirementStatusChanged() { + notifyAll(); + } + + synchronized void add(Job job) { + jobQueue.add(job); + notifyAll(); + } + + synchronized void addAll(List jobs) { + jobQueue.addAll(jobs); + notifyAll(); + } + + synchronized void push(Job job) { + jobQueue.addFirst(job); + } + + synchronized Job getNext() { + try { + Job nextAvailableJob; + + while ((nextAvailableJob = getNextAvailableJob()) == null) { + wait(); + } + + return nextAvailableJob; + } catch (InterruptedException e) { + throw new AssertionError(e); + } + } + + synchronized void setGroupIdAvailable(String groupId) { + if (groupId != null) { + activeGroupIds.remove(groupId); + notifyAll(); + } + } + + private Job getNextAvailableJob() { + if (jobQueue.isEmpty()) return null; + + ListIterator iterator = jobQueue.listIterator(); + while (iterator.hasNext()) { + Job job = iterator.next(); + + if (job.isRequirementsMet() && isGroupIdAvailable(job.getGroupId())) { + iterator.remove(); + setGroupIdUnavailable(job.getGroupId()); + return job; + } + } + + return null; + } + + private boolean isGroupIdAvailable(String groupId) { + return groupId == null || !activeGroupIds.contains(groupId); + } + + private void setGroupIdUnavailable(String groupId) { + if (groupId != null) { + activeGroupIds.add(groupId); + } + } +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/dependencies/AggregateDependencyInjector.java b/src/org/thoughtcrime/securesms/jobmanager/dependencies/AggregateDependencyInjector.java new file mode 100644 index 0000000000..c855314b7c --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/dependencies/AggregateDependencyInjector.java @@ -0,0 +1,36 @@ +package org.thoughtcrime.securesms.jobmanager.dependencies; + +import android.content.Context; + +import org.thoughtcrime.securesms.jobmanager.Job; +import org.thoughtcrime.securesms.jobmanager.requirements.Requirement; + +public class AggregateDependencyInjector { + + private final DependencyInjector dependencyInjector; + + public AggregateDependencyInjector(DependencyInjector dependencyInjector) { + this.dependencyInjector = dependencyInjector; + } + + public void injectDependencies(Context context, Job job) { + if (job instanceof ContextDependent) { + ((ContextDependent)job).setContext(context); + } + + for (Requirement requirement : job.getRequirements()) { + if (requirement instanceof ContextDependent) { + ((ContextDependent)requirement).setContext(context); + } + } + + if (dependencyInjector != null) { + dependencyInjector.injectDependencies(job); + + for (Requirement requirement : job.getRequirements()) { + dependencyInjector.injectDependencies(requirement); + } + } + } + +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/dependencies/ContextDependent.java b/src/org/thoughtcrime/securesms/jobmanager/dependencies/ContextDependent.java new file mode 100644 index 0000000000..84a4aca367 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/dependencies/ContextDependent.java @@ -0,0 +1,27 @@ +/** +* Copyright (C) 2014 Open Whisper Systems +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ +package org.thoughtcrime.securesms.jobmanager.dependencies; + +import android.content.Context; + +/** + * Any Job or Requirement that depends on {@link android.content.Context} can implement this + * interface to receive a Context after being deserialized. + */ +public interface ContextDependent { + public void setContext(Context context); +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/dependencies/DependencyInjector.java b/src/org/thoughtcrime/securesms/jobmanager/dependencies/DependencyInjector.java new file mode 100644 index 0000000000..42e1ae3ad2 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/dependencies/DependencyInjector.java @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager.dependencies; + +/** + * Interface responsible for injecting dependencies into Jobs. + */ +public interface DependencyInjector { + public void injectDependencies(Object object); +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/persistence/JavaJobSerializer.java b/src/org/thoughtcrime/securesms/jobmanager/persistence/JavaJobSerializer.java new file mode 100644 index 0000000000..655f655f30 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/persistence/JavaJobSerializer.java @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager.persistence; + +import org.thoughtcrime.securesms.jobmanager.EncryptionKeys; +import org.thoughtcrime.securesms.jobmanager.Job; +import org.thoughtcrime.securesms.jobmanager.util.Base64; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * An implementation of {@link org.thoughtcrime.securesms.jobmanager.persistence.JobSerializer} that uses + * Java Serialization. + * + * NOTE: This {@link JobSerializer} does not support encryption. Jobs will be serialized normally, + * but any corresponding {@link Job} encryption keys will be ignored. + */ +public class JavaJobSerializer implements JobSerializer { + + public JavaJobSerializer() {} + + @Override + public String serialize(Job job) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(job); + + return Base64.encodeToString(baos.toByteArray(), Base64.NO_WRAP); + } + + @Override + public Job deserialize(EncryptionKeys keys, boolean encrypted, String serialized) throws IOException { + try { + ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(serialized, Base64.NO_WRAP)); + ObjectInputStream ois = new ObjectInputStream(bais); + + return (Job)ois.readObject(); + } catch (ClassNotFoundException e) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + + throw new IOException(e.getMessage() + "\n" + sw.toString()); + } + } +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/persistence/JobSerializer.java b/src/org/thoughtcrime/securesms/jobmanager/persistence/JobSerializer.java new file mode 100644 index 0000000000..533f72cc1d --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/persistence/JobSerializer.java @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager.persistence; + +import org.thoughtcrime.securesms.jobmanager.EncryptionKeys; +import org.thoughtcrime.securesms.jobmanager.Job; + +import java.io.IOException; + +/** + * A JobSerializer is responsible for serializing and deserializing persistent jobs. + */ +public interface JobSerializer { + + /** + * Serialize a job object into a string. + * @param job The Job to serialize. + * @return The serialized Job. + * @throws IOException if serialization fails. + */ + public String serialize(Job job) throws IOException; + + /** + * Deserialize a String into a Job. + * @param keys Optional encryption keys that could have been used. + * @param encrypted True if the job was encrypted using the encryption keys. + * @param serialized The serialized Job. + * @return The deserialized Job. + * @throws IOException If the Job deserialization fails. + */ + public Job deserialize(EncryptionKeys keys, boolean encrypted, String serialized) throws IOException; + +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/persistence/PersistentStorage.java b/src/org/thoughtcrime/securesms/jobmanager/persistence/PersistentStorage.java new file mode 100644 index 0000000000..29b6044853 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/persistence/PersistentStorage.java @@ -0,0 +1,134 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager.persistence; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +import org.thoughtcrime.securesms.jobmanager.EncryptionKeys; +import org.thoughtcrime.securesms.jobmanager.Job; +import org.thoughtcrime.securesms.jobmanager.dependencies.AggregateDependencyInjector; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +public class PersistentStorage { + + private static final int DATABASE_VERSION = 1; + + private static final String TABLE_NAME = "queue"; + private static final String ID = "_id"; + private static final String ITEM = "item"; + private static final String ENCRYPTED = "encrypted"; + + private static final String DATABASE_CREATE = String.format("CREATE TABLE %s (%s INTEGER PRIMARY KEY, %s TEXT NOT NULL, %s INTEGER DEFAULT 0);", + TABLE_NAME, ID, ITEM, ENCRYPTED); + + private final Context context; + private final DatabaseHelper databaseHelper; + private final JobSerializer jobSerializer; + private final AggregateDependencyInjector dependencyInjector; + + public PersistentStorage(Context context, String name, + JobSerializer serializer, + AggregateDependencyInjector dependencyInjector) + { + this.databaseHelper = new DatabaseHelper(context, "_jobqueue-" + name); + this.context = context; + this.jobSerializer = serializer; + this.dependencyInjector = dependencyInjector; + } + + public void store(Job job) throws IOException { + ContentValues contentValues = new ContentValues(); + contentValues.put(ITEM, jobSerializer.serialize(job)); + contentValues.put(ENCRYPTED, job.getEncryptionKeys() != null); + + long id = databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues); + job.setPersistentId(id); + } + + public List getAllUnencrypted() { + return getJobs(null, ENCRYPTED + " = 0"); + } + + public List getAllEncrypted(EncryptionKeys keys) { + return getJobs(keys, ENCRYPTED + " = 1"); + } + + private List getJobs(EncryptionKeys keys, String where) { + List results = new LinkedList<>(); + SQLiteDatabase database = databaseHelper.getReadableDatabase(); + Cursor cursor = null; + + try { + cursor = database.query(TABLE_NAME, null, where, null, null, null, ID + " ASC", null); + + while (cursor.moveToNext()) { + long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID)); + String item = cursor.getString(cursor.getColumnIndexOrThrow(ITEM)); + boolean encrypted = cursor.getInt(cursor.getColumnIndexOrThrow(ENCRYPTED)) == 1; + + try{ + Job job = jobSerializer.deserialize(keys, encrypted, item); + + job.setPersistentId(id); + job.setEncryptionKeys(keys); + dependencyInjector.injectDependencies(context, job); + + results.add(job); + } catch (IOException e) { + Log.w("PersistentStore", e); + remove(id); + } + } + } finally { + if (cursor != null) + cursor.close(); + } + + return results; + } + + public void remove(long id) { + databaseHelper.getWritableDatabase() + .delete(TABLE_NAME, ID + " = ?", new String[] {String.valueOf(id)}); + } + + private static class DatabaseHelper extends SQLiteOpenHelper { + + public DatabaseHelper(Context context, String name) { + super(context, name, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(DATABASE_CREATE); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + + } + } + +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirement.java b/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirement.java new file mode 100644 index 0000000000..f20ff54820 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirement.java @@ -0,0 +1,50 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager.requirements; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; + +import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent; + +/** + * A requirement that is satisfied when a network connection is present. + */ +public class NetworkRequirement implements Requirement, ContextDependent { + + private transient Context context; + + public NetworkRequirement(Context context) { + this.context = context; + } + + public NetworkRequirement() {} + + @Override + public boolean isPresent() { + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo netInfo = cm.getActiveNetworkInfo(); + + return netInfo != null && netInfo.isConnected(); + } + + @Override + public void setContext(Context context) { + this.context = context; + } +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirementProvider.java b/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirementProvider.java new file mode 100644 index 0000000000..788c09eeef --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirementProvider.java @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager.requirements; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; + +public class NetworkRequirementProvider implements RequirementProvider { + + private RequirementListener listener; + + private final NetworkRequirement requirement; + + public NetworkRequirementProvider(Context context) { + this.requirement = new NetworkRequirement(context); + + context.getApplicationContext().registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (listener == null) { + return; + } + + if (requirement.isPresent()) { + listener.onRequirementStatusChanged(); + } + } + }, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); + } + + @Override + public void setListener(RequirementListener listener) { + this.listener = listener; + } + +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/requirements/Requirement.java b/src/org/thoughtcrime/securesms/jobmanager/requirements/Requirement.java new file mode 100644 index 0000000000..a294778a5a --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/requirements/Requirement.java @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager.requirements; + +import java.io.Serializable; + +/** + * A Requirement that must be satisfied before a Job can run. + */ +public interface Requirement extends Serializable { + /** + * @return true if the requirement is satisfied, false otherwise. + */ + public boolean isPresent(); +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementListener.java b/src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementListener.java new file mode 100644 index 0000000000..a548adfb98 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementListener.java @@ -0,0 +1,21 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager.requirements; + +public interface RequirementListener { + public void onRequirementStatusChanged(); +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementProvider.java b/src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementProvider.java new file mode 100644 index 0000000000..95e1c19af1 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementProvider.java @@ -0,0 +1,33 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.jobmanager.requirements; + +/** + * Notifies listeners when a {@link org.thoughtcrime.securesms.jobmanager.requirements.Requirement}'s + * state is likely to have changed. + */ +public interface RequirementProvider { + + /** + * The {@link org.thoughtcrime.securesms.jobmanager.requirements.RequirementListener} to call when + * a {@link org.thoughtcrime.securesms.jobmanager.requirements.Requirement}'s status is likely to + * have changed. + * + * @param listener The listener to call. + */ + public void setListener(RequirementListener listener); +} diff --git a/src/org/thoughtcrime/securesms/jobmanager/util/Base64.java b/src/org/thoughtcrime/securesms/jobmanager/util/Base64.java new file mode 100644 index 0000000000..f44b21deba --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobmanager/util/Base64.java @@ -0,0 +1,741 @@ +package org.thoughtcrime.securesms.jobmanager.util; + +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.UnsupportedEncodingException; + +/** + * Utilities for encoding and decoding the Base64 representation of + * binary data. See RFCs 2045 and 3548. + */ +public class Base64 { + /** + * Default values for encoder/decoder flags. + */ + public static final int DEFAULT = 0; + + /** + * Encoder flag bit to omit the padding '=' characters at the end + * of the output (if any). + */ + public static final int NO_PADDING = 1; + + /** + * Encoder flag bit to omit all line terminators (i.e., the output + * will be on one long line). + */ + public static final int NO_WRAP = 2; + + /** + * Encoder flag bit to indicate lines should be terminated with a + * CRLF pair instead of just an LF. Has no effect if {@code + * NO_WRAP} is specified as well. + */ + public static final int CRLF = 4; + + /** + * Encoder/decoder flag bit to indicate using the "URL and + * filename safe" variant of Base64 (see RFC 3548 section 4) where + * {@code -} and {@code _} are used in place of {@code +} and + * {@code /}. + */ + public static final int URL_SAFE = 8; + + /** + * Flag to pass to {@link android.util.Base64OutputStream} to indicate that it + * should not close the output stream it is wrapping when it + * itself is closed. + */ + public static final int NO_CLOSE = 16; + + // -------------------------------------------------------- + // shared code + // -------------------------------------------------------- + + /* package */ static abstract class Coder { + public byte[] output; + public int op; + + /** + * Encode/decode another block of input data. this.output is + * provided by the caller, and must be big enough to hold all + * the coded data. On exit, this.opwill be set to the length + * of the coded data. + * + * @param finish true if this is the final call to process for + * this object. Will finalize the coder state and + * include any final bytes in the output. + * + * @return true if the input so far is good; false if some + * error has been detected in the input stream.. + */ + public abstract boolean process(byte[] input, int offset, int len, boolean finish); + + /** + * @return the maximum number of bytes a call to process() + * could produce for the given number of input bytes. This may + * be an overestimate. + */ + public abstract int maxOutputSize(int len); + } + + // -------------------------------------------------------- + // decoding + // -------------------------------------------------------- + + /** + * Decode the Base64-encoded data in input and return the data in + * a new byte array. + * + *

The padding '=' characters at the end are considered optional, but + * if any are present, there must be the correct number of them. + * + * @param str the input String to decode, which is converted to + * bytes using the default charset + * @param flags controls certain features of the decoded output. + * Pass {@code DEFAULT} to decode standard Base64. + * + * @throws IllegalArgumentException if the input contains + * incorrect padding + */ + public static byte[] decode(String str, int flags) { + return decode(str.getBytes(), flags); + } + + /** + * Decode the Base64-encoded data in input and return the data in + * a new byte array. + * + *

The padding '=' characters at the end are considered optional, but + * if any are present, there must be the correct number of them. + * + * @param input the input array to decode + * @param flags controls certain features of the decoded output. + * Pass {@code DEFAULT} to decode standard Base64. + * + * @throws IllegalArgumentException if the input contains + * incorrect padding + */ + public static byte[] decode(byte[] input, int flags) { + return decode(input, 0, input.length, flags); + } + + /** + * Decode the Base64-encoded data in input and return the data in + * a new byte array. + * + *

The padding '=' characters at the end are considered optional, but + * if any are present, there must be the correct number of them. + * + * @param input the data to decode + * @param offset the position within the input array at which to start + * @param len the number of bytes of input to decode + * @param flags controls certain features of the decoded output. + * Pass {@code DEFAULT} to decode standard Base64. + * + * @throws IllegalArgumentException if the input contains + * incorrect padding + */ + public static byte[] decode(byte[] input, int offset, int len, int flags) { + // Allocate space for the most data the input could represent. + // (It could contain less if it contains whitespace, etc.) + Decoder decoder = new Decoder(flags, new byte[len*3/4]); + + if (!decoder.process(input, offset, len, true)) { + throw new IllegalArgumentException("bad base-64"); + } + + // Maybe we got lucky and allocated exactly enough output space. + if (decoder.op == decoder.output.length) { + return decoder.output; + } + + // Need to shorten the array, so allocate a new one of the + // right size and copy. + byte[] temp = new byte[decoder.op]; + System.arraycopy(decoder.output, 0, temp, 0, decoder.op); + return temp; + } + + /* package */ static class Decoder extends Coder { + /** + * Lookup table for turning bytes into their position in the + * Base64 alphabet. + */ + private static final int DECODE[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + + /** + * Decode lookup table for the "web safe" variant (RFC 3548 + * sec. 4) where - and _ replace + and /. + */ + private static final int DECODE_WEBSAFE[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + + /** Non-data values in the DECODE arrays. */ + private static final int SKIP = -1; + private static final int EQUALS = -2; + + /** + * States 0-3 are reading through the next input tuple. + * State 4 is having read one '=' and expecting exactly + * one more. + * State 5 is expecting no more data or padding characters + * in the input. + * State 6 is the error state; an error has been detected + * in the input and no future input can "fix" it. + */ + private int state; // state number (0 to 6) + private int value; + + final private int[] alphabet; + + public Decoder(int flags, byte[] output) { + this.output = output; + + alphabet = ((flags & URL_SAFE) == 0) ? DECODE : DECODE_WEBSAFE; + state = 0; + value = 0; + } + + /** + * @return an overestimate for the number of bytes {@code + * len} bytes could decode to. + */ + public int maxOutputSize(int len) { + return len * 3/4 + 10; + } + + /** + * Decode another block of input data. + * + * @return true if the state machine is still healthy. false if + * bad base-64 data has been detected in the input stream. + */ + public boolean process(byte[] input, int offset, int len, boolean finish) { + if (this.state == 6) return false; + + int p = offset; + len += offset; + + // Using local variables makes the decoder about 12% + // faster than if we manipulate the member variables in + // the loop. (Even alphabet makes a measurable + // difference, which is somewhat surprising to me since + // the member variable is final.) + int state = this.state; + int value = this.value; + int op = 0; + final byte[] output = this.output; + final int[] alphabet = this.alphabet; + + while (p < len) { + // Try the fast path: we're starting a new tuple and the + // next four bytes of the input stream are all data + // bytes. This corresponds to going through states + // 0-1-2-3-0. We expect to use this method for most of + // the data. + // + // If any of the next four bytes of input are non-data + // (whitespace, etc.), value will end up negative. (All + // the non-data values in decode are small negative + // numbers, so shifting any of them up and or'ing them + // together will result in a value with its top bit set.) + // + // You can remove this whole block and the output should + // be the same, just slower. + if (state == 0) { + while (p+4 <= len && + (value = ((alphabet[input[p] & 0xff] << 18) | + (alphabet[input[p+1] & 0xff] << 12) | + (alphabet[input[p+2] & 0xff] << 6) | + (alphabet[input[p+3] & 0xff]))) >= 0) { + output[op+2] = (byte) value; + output[op+1] = (byte) (value >> 8); + output[op] = (byte) (value >> 16); + op += 3; + p += 4; + } + if (p >= len) break; + } + + // The fast path isn't available -- either we've read a + // partial tuple, or the next four input bytes aren't all + // data, or whatever. Fall back to the slower state + // machine implementation. + + int d = alphabet[input[p++] & 0xff]; + + switch (state) { + case 0: + if (d >= 0) { + value = d; + ++state; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + + case 1: + if (d >= 0) { + value = (value << 6) | d; + ++state; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + + case 2: + if (d >= 0) { + value = (value << 6) | d; + ++state; + } else if (d == EQUALS) { + // Emit the last (partial) output tuple; + // expect exactly one more padding character. + output[op++] = (byte) (value >> 4); + state = 4; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + + case 3: + if (d >= 0) { + // Emit the output triple and return to state 0. + value = (value << 6) | d; + output[op+2] = (byte) value; + output[op+1] = (byte) (value >> 8); + output[op] = (byte) (value >> 16); + op += 3; + state = 0; + } else if (d == EQUALS) { + // Emit the last (partial) output tuple; + // expect no further data or padding characters. + output[op+1] = (byte) (value >> 2); + output[op] = (byte) (value >> 10); + op += 2; + state = 5; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + + case 4: + if (d == EQUALS) { + ++state; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + + case 5: + if (d != SKIP) { + this.state = 6; + return false; + } + break; + } + } + + if (!finish) { + // We're out of input, but a future call could provide + // more. + this.state = state; + this.value = value; + this.op = op; + return true; + } + + // Done reading input. Now figure out where we are left in + // the state machine and finish up. + + switch (state) { + case 0: + // Output length is a multiple of three. Fine. + break; + case 1: + // Read one extra input byte, which isn't enough to + // make another output byte. Illegal. + this.state = 6; + return false; + case 2: + // Read two extra input bytes, enough to emit 1 more + // output byte. Fine. + output[op++] = (byte) (value >> 4); + break; + case 3: + // Read three extra input bytes, enough to emit 2 more + // output bytes. Fine. + output[op++] = (byte) (value >> 10); + output[op++] = (byte) (value >> 2); + break; + case 4: + // Read one padding '=' when we expected 2. Illegal. + this.state = 6; + return false; + case 5: + // Read all the padding '='s we expected and no more. + // Fine. + break; + } + + this.state = state; + this.op = op; + return true; + } + } + + // -------------------------------------------------------- + // encoding + // -------------------------------------------------------- + + /** + * Base64-encode the given data and return a newly allocated + * String with the result. + * + * @param input the data to encode + * @param flags controls certain features of the encoded output. + * Passing {@code DEFAULT} results in output that + * adheres to RFC 2045. + */ + public static String encodeToString(byte[] input, int flags) { + try { + return new String(encode(input, flags), "US-ASCII"); + } catch (UnsupportedEncodingException e) { + // US-ASCII is guaranteed to be available. + throw new AssertionError(e); + } + } + + /** + * Base64-encode the given data and return a newly allocated + * String with the result. + * + * @param input the data to encode + * @param offset the position within the input array at which to + * start + * @param len the number of bytes of input to encode + * @param flags controls certain features of the encoded output. + * Passing {@code DEFAULT} results in output that + * adheres to RFC 2045. + */ + public static String encodeToString(byte[] input, int offset, int len, int flags) { + try { + return new String(encode(input, offset, len, flags), "US-ASCII"); + } catch (UnsupportedEncodingException e) { + // US-ASCII is guaranteed to be available. + throw new AssertionError(e); + } + } + + /** + * Base64-encode the given data and return a newly allocated + * byte[] with the result. + * + * @param input the data to encode + * @param flags controls certain features of the encoded output. + * Passing {@code DEFAULT} results in output that + * adheres to RFC 2045. + */ + public static byte[] encode(byte[] input, int flags) { + return encode(input, 0, input.length, flags); + } + + /** + * Base64-encode the given data and return a newly allocated + * byte[] with the result. + * + * @param input the data to encode + * @param offset the position within the input array at which to + * start + * @param len the number of bytes of input to encode + * @param flags controls certain features of the encoded output. + * Passing {@code DEFAULT} results in output that + * adheres to RFC 2045. + */ + public static byte[] encode(byte[] input, int offset, int len, int flags) { + Encoder encoder = new Encoder(flags, null); + + // Compute the exact length of the array we will produce. + int output_len = len / 3 * 4; + + // Account for the tail of the data and the padding bytes, if any. + if (encoder.do_padding) { + if (len % 3 > 0) { + output_len += 4; + } + } else { + switch (len % 3) { + case 0: break; + case 1: output_len += 2; break; + case 2: output_len += 3; break; + } + } + + // Account for the newlines, if any. + if (encoder.do_newline && len > 0) { + output_len += (((len-1) / (3 * Encoder.LINE_GROUPS)) + 1) * + (encoder.do_cr ? 2 : 1); + } + + encoder.output = new byte[output_len]; + encoder.process(input, offset, len, true); + + assert encoder.op == output_len; + + return encoder.output; + } + + /* package */ static class Encoder extends Coder { + /** + * Emit a new line every this many output tuples. Corresponds to + * a 76-character line length (the maximum allowable according to + * RFC 2045). + */ + public static final int LINE_GROUPS = 19; + + /** + * Lookup table for turning Base64 alphabet positions (6 bits) + * into output bytes. + */ + private static final byte ENCODE[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', + }; + + /** + * Lookup table for turning Base64 alphabet positions (6 bits) + * into output bytes. + */ + private static final byte ENCODE_WEBSAFE[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_', + }; + + final private byte[] tail; + /* package */ int tailLen; + private int count; + + final public boolean do_padding; + final public boolean do_newline; + final public boolean do_cr; + final private byte[] alphabet; + + public Encoder(int flags, byte[] output) { + this.output = output; + + do_padding = (flags & NO_PADDING) == 0; + do_newline = (flags & NO_WRAP) == 0; + do_cr = (flags & CRLF) != 0; + alphabet = ((flags & URL_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE; + + tail = new byte[2]; + tailLen = 0; + + count = do_newline ? LINE_GROUPS : -1; + } + + /** + * @return an overestimate for the number of bytes {@code + * len} bytes could encode to. + */ + public int maxOutputSize(int len) { + return len * 8/5 + 10; + } + + public boolean process(byte[] input, int offset, int len, boolean finish) { + // Using local variables makes the encoder about 9% faster. + final byte[] alphabet = this.alphabet; + final byte[] output = this.output; + int op = 0; + int count = this.count; + + int p = offset; + len += offset; + int v = -1; + + // First we need to concatenate the tail of the previous call + // with any input bytes available now and see if we can empty + // the tail. + + switch (tailLen) { + case 0: + // There was no tail. + break; + + case 1: + if (p+2 <= len) { + // A 1-byte tail with at least 2 bytes of + // input available now. + v = ((tail[0] & 0xff) << 16) | + ((input[p++] & 0xff) << 8) | + (input[p++] & 0xff); + tailLen = 0; + }; + break; + + case 2: + if (p+1 <= len) { + // A 2-byte tail with at least 1 byte of input. + v = ((tail[0] & 0xff) << 16) | + ((tail[1] & 0xff) << 8) | + (input[p++] & 0xff); + tailLen = 0; + } + break; + } + + if (v != -1) { + output[op++] = alphabet[(v >> 18) & 0x3f]; + output[op++] = alphabet[(v >> 12) & 0x3f]; + output[op++] = alphabet[(v >> 6) & 0x3f]; + output[op++] = alphabet[v & 0x3f]; + if (--count == 0) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + count = LINE_GROUPS; + } + } + + // At this point either there is no tail, or there are fewer + // than 3 bytes of input available. + + // The main loop, turning 3 input bytes into 4 output bytes on + // each iteration. + while (p+3 <= len) { + v = ((input[p] & 0xff) << 16) | + ((input[p+1] & 0xff) << 8) | + (input[p+2] & 0xff); + output[op] = alphabet[(v >> 18) & 0x3f]; + output[op+1] = alphabet[(v >> 12) & 0x3f]; + output[op+2] = alphabet[(v >> 6) & 0x3f]; + output[op+3] = alphabet[v & 0x3f]; + p += 3; + op += 4; + if (--count == 0) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + count = LINE_GROUPS; + } + } + + if (finish) { + // Finish up the tail of the input. Note that we need to + // consume any bytes in tail before any bytes + // remaining in input; there should be at most two bytes + // total. + + if (p-tailLen == len-1) { + int t = 0; + v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4; + tailLen -= t; + output[op++] = alphabet[(v >> 6) & 0x3f]; + output[op++] = alphabet[v & 0x3f]; + if (do_padding) { + output[op++] = '='; + output[op++] = '='; + } + if (do_newline) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + } + } else if (p-tailLen == len-2) { + int t = 0; + v = (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10) | + (((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2); + tailLen -= t; + output[op++] = alphabet[(v >> 12) & 0x3f]; + output[op++] = alphabet[(v >> 6) & 0x3f]; + output[op++] = alphabet[v & 0x3f]; + if (do_padding) { + output[op++] = '='; + } + if (do_newline) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + } + } else if (do_newline && op > 0 && count != LINE_GROUPS) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + } + + assert tailLen == 0; + assert p == len; + } else { + // Save the leftovers in tail to be consumed on the next + // call to encodeInternal. + + if (p == len-1) { + tail[tailLen++] = input[p]; + } else if (p == len-2) { + tail[tailLen++] = input[p]; + tail[tailLen++] = input[p+1]; + } + } + + this.op = op; + this.count = count; + + return true; + } + } + + private Base64() { } // don't instantiate +} diff --git a/src/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java index 369d3d5ed9..5f40dc409b 100644 --- a/src/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java +++ b/src/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java @@ -14,6 +14,8 @@ import org.thoughtcrime.securesms.database.AttachmentDatabase; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.events.PartProgressEvent; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.notifications.MessageNotifier; @@ -21,8 +23,6 @@ import org.thoughtcrime.securesms.util.AttachmentUtil; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.Hex; import org.thoughtcrime.securesms.util.Util; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; diff --git a/src/org/thoughtcrime/securesms/jobs/AttachmentFileNameJob.java b/src/org/thoughtcrime/securesms/jobs/AttachmentFileNameJob.java index ad91a1272c..a7d30e29f9 100644 --- a/src/org/thoughtcrime/securesms/jobs/AttachmentFileNameJob.java +++ b/src/org/thoughtcrime/securesms/jobs/AttachmentFileNameJob.java @@ -13,9 +13,9 @@ import org.thoughtcrime.securesms.crypto.AsymmetricMasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecretUtil; import org.thoughtcrime.securesms.database.DatabaseFactory; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.mms.IncomingMediaMessage; -import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.libsignal.InvalidMessageException; import java.io.IOException; diff --git a/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java index d1d1ee6a6d..41b9411fa4 100644 --- a/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java +++ b/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java @@ -10,14 +10,14 @@ import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel; import org.thoughtcrime.securesms.util.BitmapDecodingException; import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.Hex; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; diff --git a/src/org/thoughtcrime/securesms/jobs/CleanPreKeysJob.java b/src/org/thoughtcrime/securesms/jobs/CleanPreKeysJob.java index 8641b8a074..11a70df708 100644 --- a/src/org/thoughtcrime/securesms/jobs/CleanPreKeysJob.java +++ b/src/org/thoughtcrime/securesms/jobs/CleanPreKeysJob.java @@ -6,8 +6,8 @@ import android.util.Log; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.PreKeyUtil; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; -import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.libsignal.InvalidKeyIdException; import org.whispersystems.libsignal.state.SignedPreKeyRecord; import org.whispersystems.libsignal.state.SignedPreKeyStore; diff --git a/src/org/thoughtcrime/securesms/jobs/ContextJob.java b/src/org/thoughtcrime/securesms/jobs/ContextJob.java index e68f1a0a21..b8b5bb6f7e 100644 --- a/src/org/thoughtcrime/securesms/jobs/ContextJob.java +++ b/src/org/thoughtcrime/securesms/jobs/ContextJob.java @@ -2,9 +2,9 @@ package org.thoughtcrime.securesms.jobs; import android.content.Context; -import org.whispersystems.jobqueue.Job; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.dependencies.ContextDependent; +import org.thoughtcrime.securesms.jobmanager.Job; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent; public abstract class ContextJob extends Job implements ContextDependent { diff --git a/src/org/thoughtcrime/securesms/jobs/CreateSignedPreKeyJob.java b/src/org/thoughtcrime/securesms/jobs/CreateSignedPreKeyJob.java index 78639cb22c..9d19fa7931 100644 --- a/src/org/thoughtcrime/securesms/jobs/CreateSignedPreKeyJob.java +++ b/src/org/thoughtcrime/securesms/jobs/CreateSignedPreKeyJob.java @@ -7,10 +7,10 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.PreKeyUtil; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.state.SignedPreKeyRecord; import org.whispersystems.signalservice.api.SignalServiceAccountManager; diff --git a/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java b/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java index 98c58795cd..0bf788e74c 100644 --- a/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java +++ b/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java @@ -6,10 +6,10 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.DirectoryHelper; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; import java.io.IOException; diff --git a/src/org/thoughtcrime/securesms/jobs/GcmRefreshJob.java b/src/org/thoughtcrime/securesms/jobs/GcmRefreshJob.java index a104dfc10d..d0d7dedcf9 100644 --- a/src/org/thoughtcrime/securesms/jobs/GcmRefreshJob.java +++ b/src/org/thoughtcrime/securesms/jobs/GcmRefreshJob.java @@ -31,9 +31,9 @@ import com.google.android.gms.gcm.GoogleCloudMessaging; import org.thoughtcrime.securesms.PlayServicesProblemActivity; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; diff --git a/src/org/thoughtcrime/securesms/jobs/LocalBackupJob.java b/src/org/thoughtcrime/securesms/jobs/LocalBackupJob.java index e530548a94..11c921f54b 100644 --- a/src/org/thoughtcrime/securesms/jobs/LocalBackupJob.java +++ b/src/org/thoughtcrime/securesms/jobs/LocalBackupJob.java @@ -11,12 +11,12 @@ import org.thoughtcrime.securesms.backup.FullBackupExporter; import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.NoExternalStorageException; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.service.GenericForegroundService; import org.thoughtcrime.securesms.util.BackupUtil; import org.thoughtcrime.securesms.util.StorageUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; import java.io.File; import java.io.IOException; diff --git a/src/org/thoughtcrime/securesms/jobs/MasterSecretJob.java b/src/org/thoughtcrime/securesms/jobs/MasterSecretJob.java index 7d10ba1207..f3a6c68c43 100644 --- a/src/org/thoughtcrime/securesms/jobs/MasterSecretJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MasterSecretJob.java @@ -3,8 +3,8 @@ package org.thoughtcrime.securesms.jobs; import android.content.Context; import org.thoughtcrime.securesms.crypto.MasterSecret; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.service.KeyCachingService; -import org.whispersystems.jobqueue.JobParameters; public abstract class MasterSecretJob extends ContextJob { diff --git a/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java index 47285df361..a1314be8da 100644 --- a/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java @@ -19,6 +19,8 @@ import org.thoughtcrime.securesms.database.AttachmentDatabase; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult; import org.thoughtcrime.securesms.database.MmsDatabase; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.mms.ApnUnavailableException; import org.thoughtcrime.securesms.mms.CompatMmsConnection; @@ -31,8 +33,6 @@ import org.thoughtcrime.securesms.providers.SingleUseBlobProvider; import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.DuplicateMessageException; import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.libsignal.LegacyMessageException; diff --git a/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java index 3477975c43..a5ea75b984 100644 --- a/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java @@ -13,9 +13,9 @@ import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MmsDatabase; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.Util; -import org.whispersystems.jobqueue.JobParameters; public class MmsReceiveJob extends ContextJob { diff --git a/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java b/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java index b0a92a0b92..8e561be02e 100644 --- a/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java @@ -26,6 +26,8 @@ import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.NoSuchMessageException; import org.thoughtcrime.securesms.database.ThreadDatabase; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.mms.CompatMmsConnection; import org.thoughtcrime.securesms.mms.MediaConstraints; @@ -41,8 +43,6 @@ import org.thoughtcrime.securesms.util.Hex; import org.thoughtcrime.securesms.util.NumberUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java index e4e6bd538d..311df39092 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java @@ -7,10 +7,10 @@ import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.database.RecipientDatabase.BlockedReader; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.recipients.Recipient; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage; diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java index 12f1d3e19a..ab16ef633b 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java @@ -19,12 +19,12 @@ import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.IdentityDatabase; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceMessageSender; diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java index ec3d8d50ce..0dca950b5b 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java @@ -12,8 +12,8 @@ import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.GroupUtil; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceProfileKeyUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceProfileKeyUpdateJob.java index 54fd9de775..fe1cd2693f 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceProfileKeyUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceProfileKeyUpdateJob.java @@ -7,9 +7,9 @@ import android.util.Log; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadReceiptUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadReceiptUpdateJob.java index f1fcb6f918..c76e7d089b 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadReceiptUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadReceiptUpdateJob.java @@ -5,8 +5,8 @@ import android.content.Context; import android.util.Log; import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java index 5b9a3acc30..92e6eb5bbe 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java @@ -6,10 +6,10 @@ import android.util.Log; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.multidevice.ReadMessage; diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java index f6ce372968..33e661a358 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java @@ -7,9 +7,9 @@ import android.util.Log; import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.InvalidKeyException; import org.whispersystems.signalservice.api.SignalServiceMessageSender; diff --git a/src/org/thoughtcrime/securesms/jobs/PushContentReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/PushContentReceiveJob.java index 512f636235..cc8b3dd528 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushContentReceiveJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushContentReceiveJob.java @@ -3,8 +3,8 @@ package org.thoughtcrime.securesms.jobs; import android.content.Context; import android.util.Log; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.libsignal.InvalidVersionException; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java index 3d15eb54de..3ecc56176d 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java @@ -37,6 +37,7 @@ import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.MmsMessageRecord; import org.thoughtcrime.securesms.groups.GroupMessageProcessor; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.mms.IncomingMediaMessage; import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage; @@ -58,7 +59,6 @@ import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.IdentityUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.libsignal.DuplicateMessageException; import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.InvalidKeyException; diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java index 56f2ea0760..b649a4efc1 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java @@ -16,6 +16,8 @@ import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.NoSuchMessageException; import org.thoughtcrime.securesms.database.documents.NetworkFailure; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.mms.MediaConstraints; import org.thoughtcrime.securesms.mms.MmsException; @@ -25,8 +27,6 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientFormattingException; import org.thoughtcrime.securesms.transport.UndeliverableMessageException; import org.thoughtcrime.securesms.util.GroupUtil; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java index d57e8d3ca2..4e258d5018 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java @@ -9,9 +9,9 @@ import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.util.GroupUtil; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; diff --git a/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java index ccb0c9a12c..43a416e0f1 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java @@ -4,8 +4,8 @@ import android.content.Context; import android.util.Log; import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; diff --git a/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java index 3e47b95a94..202f86120d 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java @@ -9,9 +9,9 @@ import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId; import org.thoughtcrime.securesms.database.RecipientDatabase; +import org.thoughtcrime.securesms.jobmanager.JobManager; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.recipients.Recipient; -import org.whispersystems.jobqueue.JobManager; -import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; public abstract class PushReceivedJob extends ContextJob { diff --git a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java index 4642768819..87256a37dc 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java @@ -15,6 +15,8 @@ import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.events.PartProgressEvent; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; @@ -25,8 +27,6 @@ import org.thoughtcrime.securesms.util.BitmapDecodingException; import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; diff --git a/src/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java b/src/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java index e1689c1b4a..f1d07fa18a 100644 --- a/src/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java +++ b/src/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java @@ -4,9 +4,9 @@ import android.content.Context; import android.util.Log; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.push.exceptions.NetworkFailureException; diff --git a/src/org/thoughtcrime/securesms/jobs/RefreshPreKeysJob.java b/src/org/thoughtcrime/securesms/jobs/RefreshPreKeysJob.java index fe39960fdb..68aabe71b4 100644 --- a/src/org/thoughtcrime/securesms/jobs/RefreshPreKeysJob.java +++ b/src/org/thoughtcrime/securesms/jobs/RefreshPreKeysJob.java @@ -8,10 +8,10 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.PreKeyUtil; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.state.PreKeyRecord; import org.whispersystems.libsignal.state.SignedPreKeyRecord; diff --git a/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java b/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java index fe1b568afe..290de287d7 100644 --- a/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java +++ b/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java @@ -4,8 +4,8 @@ import android.content.Context; import android.support.annotation.NonNull; import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; diff --git a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java index dbc25d2b95..3b47b517d8 100644 --- a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java +++ b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java @@ -8,11 +8,11 @@ import android.util.Log; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.profiles.AvatarHelper; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.Util; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; diff --git a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java index 96faa815c0..0e0c9f75d6 100644 --- a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java +++ b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java @@ -8,17 +8,15 @@ import android.util.Log; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.service.MessageRetrievalService; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.IdentityUtil; import org.thoughtcrime.securesms.util.Util; -import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.InvalidKeyException; -import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceMessagePipe; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.crypto.ProfileCipher; diff --git a/src/org/thoughtcrime/securesms/jobs/RotateSignedPreKeyJob.java b/src/org/thoughtcrime/securesms/jobs/RotateSignedPreKeyJob.java index 050bc0240c..54dbf9a243 100644 --- a/src/org/thoughtcrime/securesms/jobs/RotateSignedPreKeyJob.java +++ b/src/org/thoughtcrime/securesms/jobs/RotateSignedPreKeyJob.java @@ -9,10 +9,10 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.PreKeyUtil; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.state.SignedPreKeyRecord; import org.whispersystems.signalservice.api.SignalServiceAccountManager; diff --git a/src/org/thoughtcrime/securesms/jobs/SendJob.java b/src/org/thoughtcrime/securesms/jobs/SendJob.java index 6b03b2935a..e5bf9c4aa0 100644 --- a/src/org/thoughtcrime/securesms/jobs/SendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/SendJob.java @@ -9,13 +9,13 @@ import org.thoughtcrime.securesms.attachments.Attachment; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.database.AttachmentDatabase; import org.thoughtcrime.securesms.database.DatabaseFactory; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.mms.MediaConstraints; import org.thoughtcrime.securesms.mms.MediaStream; import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.transport.UndeliverableMessageException; import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.Util; -import org.whispersystems.jobqueue.JobParameters; import java.io.IOException; import java.util.LinkedList; diff --git a/src/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java b/src/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java index abbeb68a13..024d89117b 100644 --- a/src/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java +++ b/src/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java @@ -6,9 +6,9 @@ import android.util.Log; import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage; diff --git a/src/org/thoughtcrime/securesms/jobs/ServiceOutageDetectionJob.java b/src/org/thoughtcrime/securesms/jobs/ServiceOutageDetectionJob.java index 2054874ce8..bf24efe932 100644 --- a/src/org/thoughtcrime/securesms/jobs/ServiceOutageDetectionJob.java +++ b/src/org/thoughtcrime/securesms/jobs/ServiceOutageDetectionJob.java @@ -6,10 +6,10 @@ import android.util.Log; import org.greenrobot.eventbus.EventBus; import org.thoughtcrime.securesms.BuildConfig; import org.thoughtcrime.securesms.events.ReminderUpdateEvent; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import java.net.InetAddress; import java.net.UnknownHostException; diff --git a/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java index a07bb3e6d1..fa0ed108e0 100644 --- a/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java +++ b/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java @@ -9,13 +9,12 @@ import android.util.Log; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult; import org.thoughtcrime.securesms.database.SmsDatabase; -import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.jobs.requirements.SqlCipherMigrationRequirement; import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.sms.IncomingTextMessage; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.libsignal.util.guava.Optional; import java.util.LinkedList; diff --git a/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java b/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java index 56d780c4a1..86eb182d6b 100644 --- a/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java @@ -23,7 +23,7 @@ import org.thoughtcrime.securesms.service.SmsDeliveryListener; import org.thoughtcrime.securesms.transport.UndeliverableMessageException; import org.thoughtcrime.securesms.util.NumberUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import java.util.ArrayList; diff --git a/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java b/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java index 91f63267c6..f2d2b3be9c 100644 --- a/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java +++ b/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java @@ -11,10 +11,10 @@ import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.NoSuchMessageException; import org.thoughtcrime.securesms.database.SmsDatabase; import org.thoughtcrime.securesms.database.model.SmsMessageRecord; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.service.SmsDeliveryListener; -import org.whispersystems.jobqueue.JobParameters; public class SmsSentJob extends MasterSecretJob { diff --git a/src/org/thoughtcrime/securesms/jobs/TrimThreadJob.java b/src/org/thoughtcrime/securesms/jobs/TrimThreadJob.java index 754e58cb52..634d0e63bb 100644 --- a/src/org/thoughtcrime/securesms/jobs/TrimThreadJob.java +++ b/src/org/thoughtcrime/securesms/jobs/TrimThreadJob.java @@ -20,9 +20,9 @@ import android.content.Context; import android.util.Log; import org.thoughtcrime.securesms.database.DatabaseFactory; +import org.thoughtcrime.securesms.jobmanager.Job; +import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.Job; -import org.whispersystems.jobqueue.JobParameters; public class TrimThreadJob extends Job { diff --git a/src/org/thoughtcrime/securesms/jobs/UpdateApkJob.java b/src/org/thoughtcrime/securesms/jobs/UpdateApkJob.java index 8d7313d177..63d55e4481 100644 --- a/src/org/thoughtcrime/securesms/jobs/UpdateApkJob.java +++ b/src/org/thoughtcrime/securesms/jobs/UpdateApkJob.java @@ -15,13 +15,13 @@ import android.util.Log; import com.fasterxml.jackson.annotation.JsonProperty; import org.thoughtcrime.securesms.BuildConfig; +import org.thoughtcrime.securesms.jobmanager.JobParameters; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.service.UpdateApkReadyListener; import org.thoughtcrime.securesms.util.FileUtils; import org.thoughtcrime.securesms.util.Hex; import org.thoughtcrime.securesms.util.JsonUtils; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; import java.io.FileInputStream; import java.io.IOException; diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirement.java b/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirement.java index 6e4f9e576f..00888ee808 100644 --- a/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirement.java +++ b/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirement.java @@ -2,9 +2,9 @@ package org.thoughtcrime.securesms.jobs.requirements; import android.content.Context; +import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent; +import org.thoughtcrime.securesms.jobmanager.requirements.Requirement; import org.thoughtcrime.securesms.service.KeyCachingService; -import org.whispersystems.jobqueue.dependencies.ContextDependent; -import org.whispersystems.jobqueue.requirements.Requirement; public class MasterSecretRequirement implements Requirement, ContextDependent { diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirementProvider.java b/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirementProvider.java index f4f1103d81..db036ff968 100644 --- a/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirementProvider.java +++ b/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirementProvider.java @@ -5,9 +5,9 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import org.thoughtcrime.securesms.jobmanager.requirements.RequirementListener; +import org.thoughtcrime.securesms.jobmanager.requirements.RequirementProvider; import org.thoughtcrime.securesms.service.KeyCachingService; -import org.whispersystems.jobqueue.requirements.RequirementListener; -import org.whispersystems.jobqueue.requirements.RequirementProvider; public class MasterSecretRequirementProvider implements RequirementProvider { diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/NetworkOrServiceRequirement.java b/src/org/thoughtcrime/securesms/jobs/requirements/NetworkOrServiceRequirement.java index 7a75ba3530..245c1ee360 100644 --- a/src/org/thoughtcrime/securesms/jobs/requirements/NetworkOrServiceRequirement.java +++ b/src/org/thoughtcrime/securesms/jobs/requirements/NetworkOrServiceRequirement.java @@ -2,9 +2,9 @@ package org.thoughtcrime.securesms.jobs.requirements; import android.content.Context; -import org.whispersystems.jobqueue.dependencies.ContextDependent; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; -import org.whispersystems.jobqueue.requirements.Requirement; +import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; +import org.thoughtcrime.securesms.jobmanager.requirements.Requirement; public class NetworkOrServiceRequirement implements Requirement, ContextDependent { diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirement.java b/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirement.java index c25e96e92d..39e081dc86 100644 --- a/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirement.java +++ b/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirement.java @@ -1,17 +1,10 @@ package org.thoughtcrime.securesms.jobs.requirements; import android.content.Context; -import android.os.Looper; -import android.os.MessageQueue; -import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; -import android.telephony.TelephonyManager; -import android.util.Log; -import org.thoughtcrime.securesms.ApplicationContext; +import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent; +import org.thoughtcrime.securesms.jobmanager.requirements.Requirement; import org.thoughtcrime.securesms.sms.TelephonyServiceState; -import org.whispersystems.jobqueue.dependencies.ContextDependent; -import org.whispersystems.jobqueue.requirements.Requirement; public class ServiceRequirement implements Requirement, ContextDependent { diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirementProvider.java b/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirementProvider.java index 867c99a188..4b7ccd08a5 100644 --- a/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirementProvider.java +++ b/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirementProvider.java @@ -5,8 +5,8 @@ import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.TelephonyManager; -import org.whispersystems.jobqueue.requirements.RequirementListener; -import org.whispersystems.jobqueue.requirements.RequirementProvider; +import org.thoughtcrime.securesms.jobmanager.requirements.RequirementListener; +import org.thoughtcrime.securesms.jobmanager.requirements.RequirementProvider; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirement.java b/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirement.java index ab5898631e..b4d6e339fb 100644 --- a/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirement.java +++ b/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirement.java @@ -4,9 +4,9 @@ package org.thoughtcrime.securesms.jobs.requirements; import android.content.Context; import android.support.annotation.NonNull; +import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent; +import org.thoughtcrime.securesms.jobmanager.requirements.Requirement; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.dependencies.ContextDependent; -import org.whispersystems.jobqueue.requirements.Requirement; public class SqlCipherMigrationRequirement implements Requirement, ContextDependent { diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirementProvider.java b/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirementProvider.java index 08c9e576a9..2ce574f515 100644 --- a/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirementProvider.java +++ b/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirementProvider.java @@ -4,8 +4,8 @@ package org.thoughtcrime.securesms.jobs.requirements; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; -import org.whispersystems.jobqueue.requirements.RequirementListener; -import org.whispersystems.jobqueue.requirements.RequirementProvider; +import org.thoughtcrime.securesms.jobmanager.requirements.RequirementListener; +import org.thoughtcrime.securesms.jobmanager.requirements.RequirementProvider; public class SqlCipherMigrationRequirementProvider implements RequirementProvider { diff --git a/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java b/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java index c7b0a6c6d2..cb93e5b99a 100644 --- a/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java +++ b/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java @@ -12,11 +12,11 @@ import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.gcm.GcmBroadcastReceiver; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirementProvider; +import org.thoughtcrime.securesms.jobmanager.requirements.RequirementListener; import org.thoughtcrime.securesms.jobs.PushContentReceiveJob; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.jobqueue.requirements.NetworkRequirement; -import org.whispersystems.jobqueue.requirements.NetworkRequirementProvider; -import org.whispersystems.jobqueue.requirements.RequirementListener; import org.whispersystems.libsignal.InvalidVersionException; import org.whispersystems.signalservice.api.SignalServiceMessagePipe; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; diff --git a/src/org/thoughtcrime/securesms/service/SmsDeliveryListener.java b/src/org/thoughtcrime/securesms/service/SmsDeliveryListener.java index 9008258976..a579f62366 100644 --- a/src/org/thoughtcrime/securesms/service/SmsDeliveryListener.java +++ b/src/org/thoughtcrime/securesms/service/SmsDeliveryListener.java @@ -8,8 +8,8 @@ import android.util.Log; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.database.SmsDatabase; +import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobs.SmsSentJob; -import org.whispersystems.jobqueue.JobManager; public class SmsDeliveryListener extends BroadcastReceiver { diff --git a/src/org/thoughtcrime/securesms/sms/MessageSender.java b/src/org/thoughtcrime/securesms/sms/MessageSender.java index 05a206bd4c..8595d8b02e 100644 --- a/src/org/thoughtcrime/securesms/sms/MessageSender.java +++ b/src/org/thoughtcrime/securesms/sms/MessageSender.java @@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.database.SmsDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.model.MessageRecord; +import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobs.MmsSendJob; import org.thoughtcrime.securesms.jobs.PushGroupSendJob; import org.thoughtcrime.securesms.jobs.PushMediaSendJob; @@ -40,7 +41,6 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.service.ExpiringMessageManager; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; -import org.whispersystems.jobqueue.JobManager; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.push.ContactTokenDetails;