mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-25 02:55:23 +00:00
Schedule jobs with WorkManager.
Should help solve most of our pressing targetSdk=26 migration issues.
This commit is contained in:
parent
d10a44f8eb
commit
87e6aa48bb
@ -541,8 +541,6 @@
|
||||
|
||||
<receiver android:name=".service.ExpirationListener" />
|
||||
|
||||
<receiver android:name=".jobmanager.requirements.BackoffReceiver" />
|
||||
|
||||
<provider android:name=".providers.PartProvider"
|
||||
android:grantUriPermissions="true"
|
||||
android:exported="false"
|
||||
|
103
build.gradle
103
build.gradle
@ -57,18 +57,21 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'com.android.support:appcompat-v7:27.0.2'
|
||||
compile 'com.android.support:recyclerview-v7:27.0.2'
|
||||
compile 'com.android.support:design:27.0.2'
|
||||
compile 'com.android.support:support-v13:27.0.2'
|
||||
compile 'com.android.support:cardview-v7:27.0.2'
|
||||
compile 'com.android.support:preference-v7:27.0.2'
|
||||
compile 'com.android.support:preference-v14:27.0.2'
|
||||
compile 'com.android.support:gridlayout-v7:27.0.2'
|
||||
compile 'com.android.support:multidex:1.0.2'
|
||||
compile 'com.android.support:exifinterface:27.0.2'
|
||||
def supportVersion = '28.0.0'
|
||||
|
||||
compile "com.android.support:appcompat-v7:$supportVersion"
|
||||
compile "com.android.support:recyclerview-v7:$supportVersion"
|
||||
compile "com.android.support:design:$supportVersion"
|
||||
compile "com.android.support:support-v13:$supportVersion"
|
||||
compile "com.android.support:cardview-v7:$supportVersion"
|
||||
compile "com.android.support:preference-v7:$supportVersion"
|
||||
compile "com.android.support:preference-v14:$supportVersion"
|
||||
compile "com.android.support:gridlayout-v7:$supportVersion"
|
||||
compile "com.android.support:exifinterface:$supportVersion"
|
||||
compile 'com.android.support:multidex:1.0.3'
|
||||
compile 'android.arch.lifecycle:extensions:1.1.1'
|
||||
compile 'android.arch.lifecycle:common-java8:1.1.1'
|
||||
compile 'android.arch.work:work-runtime:1.0.0-alpha09'
|
||||
|
||||
compile 'com.google.android.gms:play-services-gcm:9.6.1'
|
||||
compile 'com.google.android.gms:play-services-maps:9.6.1'
|
||||
@ -134,8 +137,8 @@ dependencies {
|
||||
testCompile 'org.powermock:powermock-module-junit4-rule:1.6.1'
|
||||
testCompile 'org.powermock:powermock-classloading-xstream:1.6.1'
|
||||
|
||||
androidTestCompile 'com.android.support:multidex:1.0.2'
|
||||
androidTestCompile 'com.android.support:multidex-instrumentation:1.0.2'
|
||||
androidTestCompile 'com.android.support:multidex:1.0.3'
|
||||
androidTestCompile 'com.android.support:multidex-instrumentation:1.0.3'
|
||||
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
|
||||
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
|
||||
androidTestCompile ('org.assertj:assertj-core:1.7.1') {
|
||||
@ -149,21 +152,21 @@ dependencies {
|
||||
|
||||
dependencyVerification {
|
||||
verify = [
|
||||
'com.android.support:design:fa5c27a705310e95a8f4099c98777132ed901a0d69178942306bb34cd76f0d57',
|
||||
'com.android.support:preference-v14:1fcf40bd560dc21ce55b6a292d1326d28f52dc5e4f2a64eef2f38dd95777b645',
|
||||
'com.android.support:preference-v7:d9f32ddc92f8d6a0bd86a18f4fcaff805fa021245e395b6e7dd382907443ee53',
|
||||
'com.android.support:design:7874ad1904eedc74aa41cffffb7f759d8990056f3bbbc9264911651c67c42f5f',
|
||||
'com.android.support:preference-v14:8133c6e19233fa51e036a341e6d3f4adeead3375cebf777efced0fe154c3267e',
|
||||
'com.android.support:preference-v7:75eabe936d1fc3b178450a554c4d433466036f2be6d6dccdf971eac9590fdbf5',
|
||||
'com.pnikosis:materialish-progress:d71d80e00717a096784482aee21001a9d299fec3833e4ebd87739ed36cf77c54',
|
||||
'pl.tajchert:waitingdots:2835d49e0787dbcb606c5a60021ced66578503b1e9fddcd7a5ef0cd5f095ba2c',
|
||||
'mobi.upod:time-duration-picker:db469ce0f48dd96b892eac424ed76870e54bf00fe0a28cdcddfbe5f2a226a0e1',
|
||||
'com.codewaves.stickyheadergrid:stickyheadergrid:5b4aa6a52a957cfd55f60f4220c11c0c371385a3cb9786cae03c260dcdef5794',
|
||||
'com.android.support:appcompat-v7:b2825e8b47f665d3362d8481c8d147d1af9230d16f23a2b94f6ccbc53c68cec1',
|
||||
'com.android.support:appcompat-v7:a3a8e5230359746ed91801579b5fbe4668e3b1c4e6a14c7d67c8f58cb0311752',
|
||||
'com.melnykov:floatingactionbutton:15d58d4fac0f7a288d0e5301bbaf501a146f5b3f5921277811bf99bd3b397263',
|
||||
'com.android.support:recyclerview-v7:3eb953930f10941f2b0447ec123a9b03d2746a42a99c523e82c3ece3308ca70b',
|
||||
'com.android.support:support-v13:6f2848811ceef2e32cc98da02a045d65f7e7447a6bd7198b9ec10aa14d7ad55c',
|
||||
'com.android.support:cardview-v7:57f867a3c8f33e2d4dc0a03e2dfa03cad6267a908179f04a725a68ea9f0b8ccf',
|
||||
'com.android.support:gridlayout-v7:227b5fdffa20f53bd562503aab6d2293d52cf64b5a6ab1116d2150f87bff9e88',
|
||||
'com.android.support:multidex:7cd48755c7cfdb6dd2d21cbb02236ec390f6ac91cde87eb62f475b259ab5301d',
|
||||
'com.android.support:exifinterface:0e7cd526c4468895cd8549def46b3d33c8bcfb1ae4830569898d8c7326b15bb2',
|
||||
'com.android.support:recyclerview-v7:eb296414c1f6d4c7b522f69fe50588ea85297855db0e7806c24eb4f75409587d',
|
||||
'com.android.support:support-v13:491f940c5d6d2ec7678fa2f14bd4bbbe8bf776e2c776d04bf0e5c2175975be43',
|
||||
'com.android.support:cardview-v7:bc9e6b0e06ce1205f1db34f0e6193019613d19cfeb54cdccea722340d1c60f26',
|
||||
'com.android.support:gridlayout-v7:5029529f7db66f8773426bf7318645f0840fc50d74f66355cd60c5e58d2da087',
|
||||
'com.android.support:exifinterface:bbf44e519edd6333a24a3285aa21fd00181b920b81ca8aa89a8899f03ab4d6b0',
|
||||
'android.arch.work:work-runtime:eda29b2cad202dee05a2e5aafe0a37c93ba9cde8f7cc0d0c8926a9f1a9498a8f',
|
||||
'android.arch.lifecycle:extensions:429426b2feec2245ffc5e75b3b5309bedb36159cf06dc71843ae43526ac289b6',
|
||||
'android.arch.lifecycle:common-java8:7078b5c8ccb94203df9cc2a463c69cf0021596e6cf966d78fbfd697aaafe0630',
|
||||
'com.google.android.gms:play-services-gcm:312e61253a236f2d9b750b9c04fc92fd190d23b0b2755c99de6ce4a28b259dae',
|
||||
@ -199,24 +202,44 @@ dependencyVerification {
|
||||
'com.google.android.gms:play-services-base:0ca636a8fc9a5af45e607cdcd61783bf5d561cbbb0f862021ce69606eee5ad49',
|
||||
'com.google.android.gms:play-services-tasks:69ec265168e601d0203d04cd42e34bb019b2f029aa1e16fabd38a5153eea2086',
|
||||
'com.google.android.gms:play-services-basement:95dd882c5ffba15b9a99de3fefb05d3a01946623af67454ca00055d222f85a8d',
|
||||
'com.android.support:support-v4:1b2b37169fcccfef5e563d273749e3792decdce9818bc17932403a2363f537b4',
|
||||
'com.android.support:support-fragment:e4358388022a2205777575a7251fe357334658e4123d5d6e3b082f5899d9b011',
|
||||
'com.android.support:animated-vector-drawable:5b117a2c13a898c2a3c84c480d64edcfac2ef720aa9b742c29249fac774ffc48',
|
||||
'com.android.support:support-core-ui:2284072511a95d504c074de80c82cd33724c6d2754117833b98ba3a09994163e',
|
||||
'com.android.support:transition:1a7db0453c1467fc8fd815e6d50ca6bb475a7a9ba6b5f3b307329688a7c62a68',
|
||||
'com.android.support:support-v4:8b9031381c678d628c9e47b566ae1d161e1c9710f7855c759beeac7596cecf30',
|
||||
'com.android.support:support-fragment:3772fc738ada86824ba1a4b3f197c3dbd67b7ddcfe2c9db1de95ef2e3487a915',
|
||||
'com.android.support:animated-vector-drawable:271ecbc906cda8dcd9e655ba0473129c3408a4189c806f616c378e6fd18fb3b7',
|
||||
'com.android.support:support-core-ui:bbc7f65fc95649464733af373361532ab5f9f3b749c3badaa2bbf27e574b6c6f',
|
||||
'com.android.support:transition:45d09fc51284c17bbab300f5122512ac7d7348a6d23bda2051648bbe76cc9aa5',
|
||||
'com.android.support:viewpager:013c4c53058758ec104dbae970be58159f75dfe342ba8b937d15ff5282e35ffc',
|
||||
'com.android.support:coordinatorlayout:9dfacd80423dc979048fbaed83c0ee543c46259feb2417377e79a656888d3892',
|
||||
'com.android.support:drawerlayout:8f6809afae4793550c37461c9810e954ae6a23dbb4d23e5333bf18148df1150a',
|
||||
'com.android.support:slidingpanelayout:d1d234f66a1b36a9aee9b94fa6c66f97128c0828078c8e889e9037ec898cd600',
|
||||
'com.android.support:customview:98db03845f994e08248bf701c1ff0ccaa12e70f94251ec9272900f0f694e072b',
|
||||
'com.android.support:swiperefreshlayout:a3b41f7f6730866b49865e86e49f988d4858699765f534300fb2ff5f9325e712',
|
||||
'com.android.support:asynclayoutinflater:115bde87721f7334579b0c735f60dd7c98af1bb7f34010c5b0553b95dc351aa2',
|
||||
'android.arch.persistence.room:runtime:c21810eaafce370f1c9df1365393f55f962370a0d8b0b38b4771052c7021b737',
|
||||
'com.android.support:support-core-utils:c81e1e98ca3cb2edae002c69cf35b22aec364b8cb2f1042c97e206eb5790ac41',
|
||||
'com.android.support:loader:920b85efd72dc33e915b0f88a883fe73b88483c6df8751a741e17611f2460341',
|
||||
'com.android.support:support-vector-drawable:f658986d968172bccfed28578471c96050780fe5e133861e4d331069cc373f4d',
|
||||
'com.android.support:support-media-compat:266eff9605f515013eee1ebdbd8818a9270696dc807f34bbcc5fc11fb61a22c7',
|
||||
'com.android.support:support-compat:e17e3b01dbea3f9ea1c86943292f903ca93d2231c6242e456e0b6a9c5817118a',
|
||||
'com.android.support:versionedparcelable:60eb1cb08f71b65c3f6123135e03ebeb5930b5e126e1e5b2ac91b386908c9d02',
|
||||
'com.android.support:collections:93c258c8a09f531a267653829742c0f8f6da0e348b11cb8655b0855628f2d4f0',
|
||||
'android.arch.lifecycle:livedata:50ab0490c1ff1a7cfb4e554032998b080888946d0dd424f39900efc4a1bcd750',
|
||||
'android.arch.lifecycle:livedata-core:d6fdd8b985d6178d7ea2f16986a24e83f1bee936b74d43167c69e08d3cc12c50',
|
||||
'android.arch.core:runtime:c3215aa5873311b3f88a6f4e4a3c25ad89971bc127de8c3e1291c57f93a05c39',
|
||||
'com.android.support:support-core-utils:b69c6e1e7731b876b910fc7100bcadf40a57f27b32ca26b91400995542112c96',
|
||||
'com.android.support:support-vector-drawable:bf4f4fcbf58b1380616581224e6487c230bfdb3434ec353d4adaa4b1f4865cfa',
|
||||
'com.android.support:support-media-compat:6dd9327ee9aa467cab479aad97df375072b2b6ba61eadffdaa5a88de3843c457',
|
||||
'com.android.support:support-compat:ed4d25d91a0b13d8b9def1c0de69ed03d7fb89d50fb37eb0e9b63b0cf7a42357',
|
||||
'android.arch.lifecycle:runtime:c4e4be66c1b2f0abec593571454e1de14013f7e0f96bf2a9f212931a48cae550',
|
||||
'android.arch.core:common:3a616a32f433e9e23f556b38575c31b013613d3ae85206263b7625fe1f4c151a',
|
||||
'android.arch.lifecycle:common:8d378e88ebd5189e09eef623414812c868fd90aa519d6160e2311fb8b81cff56',
|
||||
'android.arch.lifecycle:viewmodel:7de29cfaba77d6b5d5be234c57f6812d0150d087e63941af22ba1d1f8e2bc96a',
|
||||
'com.github.bumptech.glide:gifdecoder:59ccf3bb0cec11dab4b857382cbe0b171111b6fc62bf141adce4e1180889af15',
|
||||
'com.android.support:support-annotations:af05330d997eb92a066534dbe0a3ea24347d26d7001221092113ae02a8f233da',
|
||||
'com.android.support:interpolator:7bc7ee86a0db39a4b51956f3e89842d2bd962118d57d779eb6ed6b34ba0677ea',
|
||||
'com.android.support:cursoradapter:87feffe742b8d62ca8a9833abe564838bf6a672e31c7ad1306ec4006adf90d21',
|
||||
'android.arch.persistence.room:common:7cf36bcd5f59ddc4876f887e36511bfd7b111f1eb717c0e9b6e2bcc710305ae6',
|
||||
'android.arch.persistence:db-framework:bd665448330acb90a6f551a87b0ba69169da2b8ec168b92f387997339cc14311',
|
||||
'android.arch.persistence:db:504e8c4307bfd53084924776ba3d49fed11b6f76d82dd80d5121c2d907fdfef6',
|
||||
'android.arch.core:runtime:c3215aa5873311b3f88a6f4e4a3c25ad89971bc127de8c3e1291c57f93a05c39',
|
||||
'android.arch.core:common:3a616a32f433e9e23f556b38575c31b013613d3ae85206263b7625fe1f4c151a',
|
||||
'android.arch.lifecycle:viewmodel:7de29cfaba77d6b5d5be234c57f6812d0150d087e63941af22ba1d1f8e2bc96a',
|
||||
'com.android.support:documentfile:47cdcd3e9302b7b064923f05487a5c03babbd9bbda4726b71e97791fab5d4779',
|
||||
'com.android.support:localbroadcastmanager:d287c823af5fdde72c099fcfc5f630efe9687af7a914343ae6fd92de32c8a806',
|
||||
'com.android.support:print:4be8a812d73e4a80e35b91ceae127def3f0bb9726bf3bc439aa0cc81503f5728',
|
||||
'com.android.support:support-annotations:5d5b9414f02d3fa0ee7526b8d5ddae0da67c8ecc8c4d63ffa6cf91488a93b927',
|
||||
'androidx.concurrent:futures:1f63078c41efd29d20ee3444fba93c6cdfaeeb862c6d3b6166ff8debd37d471a',
|
||||
'org.whispersystems:signal-protocol-android:5b8acded7f2a40178eb90ab8e8cbfec89d170d91b3ff5e78487d1098df6185a1',
|
||||
'org.whispersystems:signal-service-java:4db9adf763071756cfd93fe48a40850f684ca02f2dea59601841abba7715c5c1',
|
||||
'com.github.bumptech.glide:disklrucache:c1b1b6f5bbd01e2fcdc9d7f60913c8d338bdb65ed4a93bfa02b56f19daaade4b',
|
||||
@ -226,6 +249,8 @@ dependencyVerification {
|
||||
'com.klinkerapps:logger:177e325259a8b111ad6745ec10db5861723c99f402222b80629f576f49408541',
|
||||
'com.google.android:flexbox:a9989fd13ae2ee42765dfc515fe362edf4f326e74925d02a10369df8092a4935',
|
||||
'org.jsoup:jsoup:abeaf34795a4de70f72aed6de5966d2955ec7eb348eeb813324f23c999575473',
|
||||
'com.google.guava:listenablefuture:e4ad7607e5c0477c6f890ef26a49cb8d1bb4dffb650bab4502afee64644e3069',
|
||||
'androidx.annotation:annotation:04f22f257944ce223701d5aa1bdc36fb7f4594e87b539044045cd161d965468e',
|
||||
'org.whispersystems:curve25519-android:82595394422b957d4a5b5f1b27b75ba25cf6dc4db4d312418ca38cd6fff279ca',
|
||||
'org.whispersystems:signal-protocol-java:5152c2b01a25147967d6bf82e540f947901bdfa79260be3eb3e96b03f787d6b5',
|
||||
'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74',
|
||||
@ -245,8 +270,8 @@ dependencyVerification {
|
||||
|
||||
android {
|
||||
flavorDimensions "none"
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion '27.0.1'
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion '27.0.3'
|
||||
useLibrary 'org.apache.http.legacy'
|
||||
|
||||
dexOptions {
|
||||
@ -258,7 +283,7 @@ android {
|
||||
versionName "4.26.2"
|
||||
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 25
|
||||
targetSdkVersion 26
|
||||
multiDexEnabled true
|
||||
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
@ -292,6 +317,7 @@ android {
|
||||
exclude 'asm-license.txt'
|
||||
exclude 'META-INF/LICENSE'
|
||||
exclude 'META-INF/NOTICE'
|
||||
exclude 'META-INF/proguard/androidx-annotations.pro'
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
@ -319,6 +345,7 @@ android {
|
||||
'proguard-retrolambda.pro',
|
||||
'proguard-okhttp.pro',
|
||||
'proguard-ez-vcard.pro',
|
||||
'proguard-workmanager.pro',
|
||||
'proguard.cfg'
|
||||
testProguardFiles 'proguard-automation.pro',
|
||||
'proguard.cfg'
|
||||
|
1
proguard-workmanager.pro
Normal file
1
proguard-workmanager.pro
Normal file
@ -0,0 +1 @@
|
||||
-dontwarn sun.misc.Unsafe
|
@ -17,8 +17,6 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.arch.lifecycle.DefaultLifecycleObserver;
|
||||
import android.arch.lifecycle.LifecycleOwner;
|
||||
import android.arch.lifecycle.ProcessLifecycleOwner;
|
||||
@ -27,7 +25,6 @@ import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.multidex.MultiDexApplication;
|
||||
import android.support.v4.app.NotificationManagerCompat;
|
||||
|
||||
import com.google.android.gms.security.ProviderInstaller;
|
||||
|
||||
@ -37,14 +34,9 @@ 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.MultiDeviceContactUpdateJob;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirementProvider;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.ServiceRequirementProvider;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.SqlCipherMigrationRequirementProvider;
|
||||
import org.thoughtcrime.securesms.logging.AndroidLogger;
|
||||
import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
@ -58,6 +50,7 @@ import org.thoughtcrime.securesms.service.LocalBackupListener;
|
||||
import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener;
|
||||
import org.thoughtcrime.securesms.service.UpdateApkRefreshListener;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.webrtc.PeerConnectionFactory;
|
||||
import org.webrtc.PeerConnectionFactory.InitializationOptions;
|
||||
import org.webrtc.voiceengine.WebRtcAudioManager;
|
||||
@ -68,6 +61,7 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import androidx.work.WorkManager;
|
||||
import dagger.ObjectGraph;
|
||||
|
||||
/**
|
||||
@ -86,6 +80,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
private JobManager jobManager;
|
||||
private ObjectGraph objectGraph;
|
||||
private PersistentLogger persistentLogger;
|
||||
private boolean initialized;
|
||||
|
||||
private volatile boolean isAppVisible;
|
||||
|
||||
@ -95,20 +90,33 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
initializeRandomNumberFix();
|
||||
initializeLogging();
|
||||
initializeCrashHandling();
|
||||
initializeDependencyInjection();
|
||||
initializeJobManager();
|
||||
initializeExpiringMessageManager();
|
||||
initializeGcmCheck();
|
||||
initializeSignedPreKeyCheck();
|
||||
initializePeriodicTasks();
|
||||
initializeCircumvention();
|
||||
initializeWebRtc();
|
||||
NotificationChannels.create(this);
|
||||
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
|
||||
synchronized (this) {
|
||||
super.onCreate();
|
||||
initializeRandomNumberFix();
|
||||
initializeLogging();
|
||||
initializeCrashHandling();
|
||||
initializeDependencyInjection();
|
||||
initializeJobManager();
|
||||
initializeExpiringMessageManager();
|
||||
initializeGcmCheck();
|
||||
initializeSignedPreKeyCheck();
|
||||
initializePeriodicTasks();
|
||||
initializeCircumvention();
|
||||
initializeWebRtc();
|
||||
NotificationChannels.create(this);
|
||||
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
|
||||
|
||||
initialized = true;
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void ensureInitialized() {
|
||||
synchronized (this) {
|
||||
while (!initialized) {
|
||||
Util.wait(this, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -164,16 +172,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
}
|
||||
|
||||
private void initializeJobManager() {
|
||||
this.jobManager = JobManager.newBuilder(this)
|
||||
.withName("TextSecureJobs")
|
||||
.withDependencyInjector(this)
|
||||
.withJobSerializer(new JavaJobSerializer())
|
||||
.withRequirementProviders(new MasterSecretRequirementProvider(this),
|
||||
new ServiceRequirementProvider(this),
|
||||
new NetworkRequirementProvider(this),
|
||||
new SqlCipherMigrationRequirementProvider())
|
||||
.withConsumerThreads(5)
|
||||
.build();
|
||||
this.jobManager = new JobManager(WorkManager.getInstance());
|
||||
}
|
||||
|
||||
private void initializeDependencyInjection() {
|
||||
|
@ -25,6 +25,11 @@ import android.database.Cursor;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.jobmanager.persistence.JavaJobSerializer;
|
||||
import org.thoughtcrime.securesms.jobmanager.persistence.PersistentStorage;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
@ -85,6 +90,7 @@ public class DatabaseUpgradeActivity extends BaseActivity {
|
||||
public static final int FULL_TEXT_SEARCH = 358;
|
||||
public static final int BAD_IMPORT_CLEANUP = 373;
|
||||
public static final int IMAGE_CACHE_CLEANUP = 406;
|
||||
public static final int WORKMANAGER_MIGRATION = 408;
|
||||
|
||||
private static final SortedSet<Integer> UPGRADE_VERSIONS = new TreeSet<Integer>() {{
|
||||
add(NO_MORE_KEY_EXCHANGE_PREFIX_VERSION);
|
||||
@ -108,6 +114,7 @@ public class DatabaseUpgradeActivity extends BaseActivity {
|
||||
add(FULL_TEXT_SEARCH);
|
||||
add(BAD_IMPORT_CLEANUP);
|
||||
add(IMAGE_CACHE_CLEANUP);
|
||||
add(WORKMANAGER_MIGRATION);
|
||||
}};
|
||||
|
||||
private MasterSecret masterSecret;
|
||||
@ -318,6 +325,18 @@ public class DatabaseUpgradeActivity extends BaseActivity {
|
||||
}
|
||||
}
|
||||
|
||||
if (params[0] < WORKMANAGER_MIGRATION) {
|
||||
Log.i(TAG, "Beginning migration of existing jobs to WorkManager");
|
||||
|
||||
JobManager jobManager = ApplicationContext.getInstance(getApplicationContext()).getJobManager();
|
||||
PersistentStorage storage = new PersistentStorage(getApplicationContext(), "TextSecureJobs", new JavaJobSerializer());
|
||||
|
||||
for (Job job : storage.getAllUnencrypted()) {
|
||||
jobManager.add(job);
|
||||
Log.i(TAG, "Migrated job with class '" + job.getClass().getSimpleName() + "' to run on new JobManager.");
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -254,7 +254,7 @@ public class QuickAttachmentDrawer extends ViewGroup implements InputView, Camer
|
||||
@Override
|
||||
protected boolean drawChild(@NonNull Canvas canvas, @NonNull View child, long drawingTime) {
|
||||
boolean result;
|
||||
final int save = canvas.save(Canvas.CLIP_SAVE_FLAG);
|
||||
final int save = canvas.save();
|
||||
|
||||
canvas.getClipBounds(drawChildrenRect);
|
||||
if (child == coverView) {
|
||||
|
@ -1,138 +1,139 @@
|
||||
/**
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.jobmanager;
|
||||
|
||||
import android.os.PowerManager;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.requirements.Requirement;
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.SqlCipherMigrationRequirement;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
import androidx.work.Data;
|
||||
import androidx.work.Worker;
|
||||
import androidx.work.WorkerParameters;
|
||||
|
||||
private final JobParameters parameters;
|
||||
public abstract class Job extends Worker implements Serializable {
|
||||
|
||||
private transient long persistentId;
|
||||
private transient int runIteration;
|
||||
private transient long lastRunTime;
|
||||
private transient PowerManager.WakeLock wakeLock;
|
||||
private static final long serialVersionUID = -4658540468214421276L;
|
||||
|
||||
public Job(JobParameters parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
private static final String TAG = Job.class.getSimpleName();
|
||||
|
||||
public List<Requirement> getRequirements() {
|
||||
return parameters.getRequirements();
|
||||
}
|
||||
static final String KEY_RETRY_COUNT = "Job_retry_count";
|
||||
static final String KEY_RETRY_UNTIL = "Job_retry_until";
|
||||
static final String KEY_SUBMIT_TIME = "Job_submit_time";
|
||||
static final String KEY_REQUIRES_MASTER_SECRET = "Job_requires_master_secret";
|
||||
static final String KEY_REQUIRES_SQLCIPHER = "Job_requires_sqlcipher";
|
||||
|
||||
public boolean isRequirementsMet() {
|
||||
for (Requirement requirement : parameters.getRequirements()) {
|
||||
if (!requirement.isPresent(this)) return false;
|
||||
}
|
||||
private JobParameters parameters;
|
||||
|
||||
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 long getRetryUntil() {
|
||||
return parameters.getRetryUntil();
|
||||
}
|
||||
|
||||
public long getLastRunTime() {
|
||||
return lastRunTime;
|
||||
}
|
||||
|
||||
public void resetRunStats() {
|
||||
runIteration = 0;
|
||||
lastRunTime = 0;
|
||||
}
|
||||
|
||||
public void setPersistentId(long persistentId) {
|
||||
this.persistentId = persistentId;
|
||||
}
|
||||
|
||||
public long getPersistentId() {
|
||||
return persistentId;
|
||||
}
|
||||
|
||||
public int getRunIteration() {
|
||||
return 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;
|
||||
}
|
||||
|
||||
public void onRetry() {
|
||||
runIteration++;
|
||||
lastRunTime = System.currentTimeMillis();
|
||||
|
||||
for (Requirement requirement : parameters.getRequirements()) {
|
||||
requirement.onRetry(this);
|
||||
}
|
||||
public Job(@NonNull Context context, @NonNull WorkerParameters workerParams) {
|
||||
super(context, workerParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Invoked when a job is first created in our own codebase.
|
||||
*/
|
||||
public abstract void onAdded();
|
||||
protected Job(@Nullable JobParameters parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Result doWork() {
|
||||
Data data = getInputData();
|
||||
|
||||
log("doWork()" + logSuffix());
|
||||
|
||||
ApplicationContext.getInstance(getApplicationContext()).ensureInitialized();
|
||||
ApplicationContext.getInstance(getApplicationContext()).injectDependencies(this);
|
||||
|
||||
if (this instanceof ContextDependent) {
|
||||
((ContextDependent)this).setContext(getApplicationContext());
|
||||
}
|
||||
|
||||
initialize(new SafeData(data));
|
||||
|
||||
try {
|
||||
if (withinRetryLimits(data)) {
|
||||
if (requirementsMet(data)) {
|
||||
onRun();
|
||||
log("Successfully completed." + logSuffix());
|
||||
return Result.SUCCESS;
|
||||
} else {
|
||||
log("Retrying due to unmet requirements." + logSuffix());
|
||||
return retry();
|
||||
}
|
||||
} else {
|
||||
warn("Failing after hitting the retry limit." + logSuffix());
|
||||
return cancel();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (onShouldRetry(e)) {
|
||||
log("Retrying after a retryable exception." + logSuffix());
|
||||
return retry();
|
||||
}
|
||||
warn("Failing due to an exception." + logSuffix(), e);
|
||||
return cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopped(boolean cancelled) {
|
||||
if (cancelled) {
|
||||
warn("onStopped() with cancellation signal." + logSuffix());
|
||||
onCanceled();
|
||||
}
|
||||
}
|
||||
|
||||
final void onSubmit(UUID id) {
|
||||
log(id, "onSubmit()");
|
||||
onAdded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after a run has finished and we've determined a retry is required, but before the next
|
||||
* attempt is run.
|
||||
*/
|
||||
protected void onRetry() { }
|
||||
|
||||
/**
|
||||
* Called after a job has been added to the JobManager queue. Invoked off the main thread, so its
|
||||
* safe to do longer-running work. However, work should finish relatively quickly, as it will
|
||||
* block the submission of future tasks.
|
||||
*/
|
||||
protected void onAdded() { }
|
||||
|
||||
/**
|
||||
* All instance state needs to be persisted in the provided {@link Data.Builder} so that it can
|
||||
* be restored in {@link #initialize(SafeData)}.
|
||||
* @param dataBuilder The builder where you put your state.
|
||||
* @return The result of {@code dataBuilder.build()}.
|
||||
*/
|
||||
protected abstract @NonNull Data serialize(@NonNull Data.Builder dataBuilder);
|
||||
|
||||
/**
|
||||
* Restore all of your instance state from the provided {@link Data}. It should contain all of
|
||||
* the data put in during {@link #serialize(Data.Builder)}.
|
||||
* @param data Where your data is stored.
|
||||
*/
|
||||
protected abstract void initialize(@NonNull SafeData data);
|
||||
|
||||
/**
|
||||
* Called to actually execute the job.
|
||||
* @throws Exception
|
||||
*/
|
||||
protected abstract void onRun() throws Exception;
|
||||
public abstract void onRun() throws Exception;
|
||||
|
||||
/**
|
||||
* Called if a job fails to run (onShouldRetry returned false, or the number of retries exceeded
|
||||
* the job's configured retry count.
|
||||
*/
|
||||
protected abstract void onCanceled();
|
||||
|
||||
/**
|
||||
* If onRun() throws an exception, this method will be called to determine whether the
|
||||
@ -141,14 +142,69 @@ public abstract class Job implements Serializable {
|
||||
* @param exception The exception onRun() threw.
|
||||
* @return true if onRun() should be called again, false otherwise.
|
||||
*/
|
||||
public abstract boolean onShouldRetry(Exception exception);
|
||||
protected 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();
|
||||
@Nullable JobParameters getJobParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private Result retry() {
|
||||
onRetry();
|
||||
return Result.RETRY;
|
||||
}
|
||||
|
||||
private Result cancel() {
|
||||
onCanceled();
|
||||
return Result.SUCCESS;
|
||||
}
|
||||
|
||||
private boolean requirementsMet(Data data) {
|
||||
boolean met = true;
|
||||
|
||||
if (data.getBoolean(KEY_REQUIRES_MASTER_SECRET, false)) {
|
||||
met &= new MasterSecretRequirement(getApplicationContext()).isPresent();
|
||||
}
|
||||
|
||||
if (data.getBoolean(KEY_REQUIRES_SQLCIPHER, false)) {
|
||||
met &= new SqlCipherMigrationRequirement(getApplicationContext()).isPresent();
|
||||
}
|
||||
|
||||
return met;
|
||||
}
|
||||
|
||||
private boolean withinRetryLimits(Data data) {
|
||||
int retryCount = data.getInt(KEY_RETRY_COUNT, 0);
|
||||
long retryUntil = data.getLong(KEY_RETRY_UNTIL, 0);
|
||||
|
||||
if (retryCount > 0) {
|
||||
return getRunAttemptCount() <= retryCount;
|
||||
}
|
||||
|
||||
return System.currentTimeMillis() < retryUntil;
|
||||
}
|
||||
|
||||
private void log(@NonNull String message) {
|
||||
log(getId(), message);
|
||||
}
|
||||
|
||||
private void log(@NonNull UUID id, @NonNull String message) {
|
||||
Log.i(TAG, buildLog(id, message));
|
||||
}
|
||||
|
||||
private void warn(@NonNull String message) {
|
||||
warn(message, null);
|
||||
}
|
||||
|
||||
private void warn(@NonNull String message, @Nullable Throwable t) {
|
||||
Log.w(TAG, buildLog(getId(), message), t);
|
||||
}
|
||||
|
||||
private String buildLog(@NonNull UUID id, @NonNull String message) {
|
||||
return "[" + id + "] " + getClass().getSimpleName() + " :: " + message;
|
||||
}
|
||||
|
||||
private String logSuffix() {
|
||||
long timeSinceSubmission = System.currentTimeMillis() - getInputData().getLong(KEY_SUBMIT_TIME, 0);
|
||||
return " (Time since submission: " + timeSinceSubmission + " ms, Run attempt: " + getRunAttemptCount() + ")";
|
||||
}
|
||||
}
|
||||
|
@ -1,100 +0,0 @@
|
||||
/**
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.jobmanager;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import org.thoughtcrime.securesms.logging.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) {
|
||||
while (canRetry(job)) {
|
||||
try {
|
||||
job.onRun();
|
||||
return JobResult.SUCCESS;
|
||||
} catch (Exception exception) {
|
||||
Log.w(TAG, exception);
|
||||
if (exception instanceof RuntimeException) {
|
||||
throw (RuntimeException)exception;
|
||||
} else if (!job.onShouldRetry(exception)) {
|
||||
return JobResult.FAILURE;
|
||||
}
|
||||
|
||||
job.onRetry();
|
||||
if (!job.isRequirementsMet()) {
|
||||
return JobResult.DEFERRED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JobResult.FAILURE;
|
||||
}
|
||||
|
||||
private boolean canRetry(@NonNull Job job) {
|
||||
if (job.getRetryCount() > 0) {
|
||||
return job.getRunIteration() < job.getRetryCount();
|
||||
}
|
||||
return System.currentTimeMillis() < job.getRetryUntil();
|
||||
}
|
||||
}
|
@ -1,252 +1,69 @@
|
||||
/**
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.jobmanager;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.PowerManager;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
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 org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
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;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
import androidx.work.BackoffPolicy;
|
||||
import androidx.work.Constraints;
|
||||
import androidx.work.Data;
|
||||
import androidx.work.ExistingWorkPolicy;
|
||||
import androidx.work.NetworkType;
|
||||
import androidx.work.OneTimeWorkRequest;
|
||||
import androidx.work.WorkManager;
|
||||
|
||||
private final JobQueue jobQueue = new JobQueue();
|
||||
private final Executor eventExecutor = Executors.newSingleThreadExecutor();
|
||||
private final AtomicBoolean hasLoadedEncrypted = new AtomicBoolean(false);
|
||||
public class JobManager {
|
||||
|
||||
private final Context context;
|
||||
private final PersistentStorage persistentStorage;
|
||||
private final List<RequirementProvider> requirementProviders;
|
||||
private final AggregateDependencyInjector dependencyInjector;
|
||||
private static final Constraints NETWORK_CONSTRAINT = new Constraints.Builder()
|
||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||
.build();
|
||||
|
||||
private JobManager(Context context, String name,
|
||||
List<RequirementProvider> 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;
|
||||
private final Executor executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
eventExecutor.execute(new LoadTask(null));
|
||||
private final WorkManager workManager;
|
||||
|
||||
if (requirementProviders != null && !requirementProviders.isEmpty()) {
|
||||
for (RequirementProvider provider : requirementProviders) {
|
||||
provider.setListener(this);
|
||||
public JobManager(@NonNull WorkManager workManager) {
|
||||
this.workManager = workManager;
|
||||
}
|
||||
|
||||
public void add(Job job) {
|
||||
executor.execute(() -> {
|
||||
workManager.synchronous().pruneWorkSync();
|
||||
|
||||
JobParameters jobParameters = job.getJobParameters();
|
||||
|
||||
if (jobParameters == null) {
|
||||
throw new IllegalStateException("Jobs must have JobParameters at this stage.");
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0;i<consumers;i++) {
|
||||
new JobConsumer("JobConsumer-" + i, jobQueue, persistentStorage).start();
|
||||
}
|
||||
}
|
||||
Data.Builder dataBuilder = new Data.Builder().putInt(Job.KEY_RETRY_COUNT, jobParameters.getRetryCount())
|
||||
.putLong(Job.KEY_RETRY_UNTIL, jobParameters.getRetryUntil())
|
||||
.putLong(Job.KEY_SUBMIT_TIME, System.currentTimeMillis())
|
||||
.putBoolean(Job.KEY_REQUIRES_MASTER_SECRET, jobParameters.requiresMasterSecret())
|
||||
.putBoolean(Job.KEY_REQUIRES_SQLCIPHER, jobParameters.requiresSqlCipher());
|
||||
Data data = job.serialize(dataBuilder);
|
||||
|
||||
/**
|
||||
* @param context An Android {@link android.content.Context}.
|
||||
* @return a {@link org.thoughtcrime.securesms.jobmanager.JobManager.Builder} used to construct a JobManager.
|
||||
*/
|
||||
public static Builder newBuilder(Context context) {
|
||||
return new Builder(context);
|
||||
}
|
||||
OneTimeWorkRequest.Builder requestBuilder = new OneTimeWorkRequest.Builder(job.getClass())
|
||||
.setInputData(data)
|
||||
.setBackoffCriteria(BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS);
|
||||
|
||||
public void setEncryptionKeys(EncryptionKeys keys) {
|
||||
if (hasLoadedEncrypted.compareAndSet(false, true)) {
|
||||
eventExecutor.execute(new LoadTask(keys));
|
||||
}
|
||||
}
|
||||
if (jobParameters.requiresNetwork()) {
|
||||
requestBuilder.setConstraints(NETWORK_CONSTRAINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue a {@link org.thoughtcrime.securesms.jobmanager.Job} to be executed.
|
||||
*
|
||||
* @param job The Job to be executed.
|
||||
*/
|
||||
public void add(final Job job) {
|
||||
if (job.needsWakeLock()) {
|
||||
job.setWakeLock(acquireWakeLock(context, job.toString(), job.getWakeLockTimeout()));
|
||||
}
|
||||
OneTimeWorkRequest request = requestBuilder.build();
|
||||
|
||||
eventExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (job.isPersistent()) {
|
||||
persistentStorage.store(job);
|
||||
}
|
||||
job.onSubmit(request.getId());
|
||||
|
||||
dependencyInjector.injectDependencies(context, job);
|
||||
|
||||
job.onAdded();
|
||||
jobQueue.add(job);
|
||||
} catch (IOException e) {
|
||||
Log.w("JobManager", e);
|
||||
job.onCanceled();
|
||||
}
|
||||
String groupId = jobParameters.getGroupId();
|
||||
if (groupId != null) {
|
||||
ExistingWorkPolicy policy = jobParameters.shouldIgnoreDuplicates() ? ExistingWorkPolicy.KEEP : ExistingWorkPolicy.APPEND;
|
||||
workManager.beginUniqueWork(groupId, policy, request).enqueue();
|
||||
} else {
|
||||
workManager.beginWith(request).enqueue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequirementStatusChanged() {
|
||||
eventExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
jobQueue.onRequirementStatusChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private PowerManager.WakeLock acquireWakeLock(Context context, String name, long timeout) {
|
||||
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name);
|
||||
|
||||
if (timeout == 0) wakeLock.acquire();
|
||||
else wakeLock.acquire(timeout);
|
||||
|
||||
return wakeLock;
|
||||
}
|
||||
|
||||
private class LoadTask implements Runnable {
|
||||
|
||||
private final EncryptionKeys keys;
|
||||
|
||||
public LoadTask(EncryptionKeys keys) {
|
||||
this.keys = keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
List<Job> 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<RequirementProvider> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,12 +16,16 @@
|
||||
*/
|
||||
package org.thoughtcrime.securesms.jobmanager;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.requirements.NetworkBackoffRequirement;
|
||||
import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
|
||||
import org.thoughtcrime.securesms.jobmanager.requirements.Requirement;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.NetworkOrServiceRequirement;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.SqlCipherMigrationRequirement;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* The set of parameters that describe a {@link org.thoughtcrime.securesms.jobmanager.Job}.
|
||||
@ -30,46 +34,86 @@ public class JobParameters implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4880456378402584584L;
|
||||
|
||||
private transient EncryptionKeys encryptionKeys;
|
||||
|
||||
private final List<Requirement> requirements;
|
||||
private final boolean isPersistent;
|
||||
private final boolean requiresNetwork;
|
||||
private final boolean requiresMasterSecret;
|
||||
private final boolean requiresSqlCipher;
|
||||
private final int retryCount;
|
||||
private final long retryUntil;
|
||||
private final String groupId;
|
||||
private final boolean wakeLock;
|
||||
private final long wakeLockTimeout;
|
||||
private final boolean ignoreDuplicates;
|
||||
|
||||
private JobParameters(List<Requirement> requirements,
|
||||
boolean isPersistent, String groupId,
|
||||
EncryptionKeys encryptionKeys,
|
||||
int retryCount, long retryUntil, boolean wakeLock,
|
||||
long wakeLockTimeout)
|
||||
private JobParameters(String groupId,
|
||||
boolean ignoreDuplicates,
|
||||
boolean requiresNetwork,
|
||||
boolean requiresMasterSecret,
|
||||
boolean requiresSqlCipher,
|
||||
int retryCount,
|
||||
long retryUntil)
|
||||
{
|
||||
this.requirements = requirements;
|
||||
this.isPersistent = isPersistent;
|
||||
this.groupId = groupId;
|
||||
this.encryptionKeys = encryptionKeys;
|
||||
this.retryCount = retryCount;
|
||||
this.retryUntil = retryUntil;
|
||||
this.wakeLock = wakeLock;
|
||||
this.wakeLockTimeout = wakeLockTimeout;
|
||||
this.groupId = groupId;
|
||||
this.ignoreDuplicates = ignoreDuplicates;
|
||||
this.requirements = Collections.emptyList();
|
||||
this.requiresNetwork = requiresNetwork;
|
||||
this.requiresMasterSecret = requiresMasterSecret;
|
||||
this.requiresSqlCipher = requiresSqlCipher;
|
||||
this.retryCount = retryCount;
|
||||
this.retryUntil = retryUntil;
|
||||
}
|
||||
|
||||
public List<Requirement> getRequirements() {
|
||||
return requirements;
|
||||
public boolean shouldIgnoreDuplicates() {
|
||||
return ignoreDuplicates;
|
||||
}
|
||||
|
||||
public boolean isPersistent() {
|
||||
return isPersistent;
|
||||
public boolean requiresNetwork() {
|
||||
return requiresNetwork || hasNetworkRequirement(requirements);
|
||||
}
|
||||
|
||||
public EncryptionKeys getEncryptionKeys() {
|
||||
return encryptionKeys;
|
||||
public boolean requiresMasterSecret() {
|
||||
return requiresMasterSecret || hasMasterSecretRequirement(requirements);
|
||||
}
|
||||
|
||||
public void setEncryptionKeys(EncryptionKeys encryptionKeys) {
|
||||
this.encryptionKeys = encryptionKeys;
|
||||
public boolean requiresSqlCipher() {
|
||||
return requiresSqlCipher || hasSqlCipherRequirement(requirements);
|
||||
}
|
||||
|
||||
private boolean hasNetworkRequirement(List<Requirement> requirements) {
|
||||
if (requirements == null || requirements.size() == 0) return false;
|
||||
|
||||
for (Requirement requirement : requirements) {
|
||||
if (requirement instanceof NetworkRequirement ||
|
||||
requirement instanceof NetworkOrServiceRequirement ||
|
||||
requirement instanceof NetworkBackoffRequirement)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasMasterSecretRequirement(List<Requirement> requirements) {
|
||||
if (requirements == null || requirements.size() == 0) return false;
|
||||
|
||||
for (Requirement requirement : requirements) {
|
||||
if (requirement instanceof MasterSecretRequirement) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasSqlCipherRequirement(List<Requirement> requirements) {
|
||||
if (requirements == null || requirements.size() == 0) return false;
|
||||
|
||||
for (Requirement requirement : requirements) {
|
||||
if (requirement instanceof SqlCipherMigrationRequirement) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getRetryCount() {
|
||||
@ -91,52 +135,29 @@ public class JobParameters implements Serializable {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public boolean needsWakeLock() {
|
||||
return wakeLock;
|
||||
}
|
||||
|
||||
public long getWakeLockTimeout() {
|
||||
return wakeLockTimeout;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private List<Requirement> requirements = new LinkedList<>();
|
||||
private boolean isPersistent = false;
|
||||
private EncryptionKeys encryptionKeys = null;
|
||||
private int retryCount = 100;
|
||||
private long retryDuration = 0;
|
||||
private String groupId = null;
|
||||
private boolean wakeLock = false;
|
||||
private long wakeLockTimeout = 0;
|
||||
private int retryCount = 100;
|
||||
private long retryDuration = 0;
|
||||
private String groupId = null;
|
||||
private boolean ignoreDuplicates = false;
|
||||
private boolean requiresNetwork = false;
|
||||
private boolean requiresSqlCipher = false;
|
||||
private boolean requiresMasterSecret = false;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
public Builder withNetworkRequirement() {
|
||||
requiresNetwork = true;
|
||||
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;
|
||||
@Deprecated
|
||||
public Builder withMasterSecretRequirement() {
|
||||
requiresMasterSecret = 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;
|
||||
@Deprecated
|
||||
public Builder withSqlCipherRequirement() {
|
||||
requiresSqlCipher = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -153,6 +174,11 @@ public class JobParameters implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify for how long we should keep retrying this job. Ignored if retryCount is set.
|
||||
* @param duration The duration (in ms) for how long we should keep retrying this job for.
|
||||
* @return the builder
|
||||
*/
|
||||
public Builder withRetryDuration(long duration) {
|
||||
this.retryDuration = duration;
|
||||
this.retryCount = 0;
|
||||
@ -172,35 +198,25 @@ public class JobParameters implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether this job should hold a wake lock.
|
||||
* If true, only one job with this groupId can be active at a time. If a job with the same
|
||||
* groupId is already running, then subsequent jobs will be ignored silently. Only has an effect
|
||||
* if a groupId has been specified via {@link #withGroupId(String)}.
|
||||
* <p />
|
||||
* Defaults to false.
|
||||
*
|
||||
* @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.
|
||||
* @param ignoreDuplicates Whether to ignore duplicates.
|
||||
* @return the builder
|
||||
*/
|
||||
public Builder withWakeLock(boolean needsWakeLock, long timeout, TimeUnit unit) {
|
||||
this.wakeLock = needsWakeLock;
|
||||
this.wakeLockTimeout = unit.toMillis(timeout);
|
||||
public Builder withDuplicatesIgnored(boolean ignoreDuplicates) {
|
||||
this.ignoreDuplicates = ignoreDuplicates;
|
||||
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, System.currentTimeMillis() + retryDuration, wakeLock, wakeLockTimeout);
|
||||
return new JobParameters(groupId, ignoreDuplicates, requiresNetwork, requiresMasterSecret, requiresSqlCipher, retryCount, System.currentTimeMillis() + retryDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,118 +0,0 @@
|
||||
/**
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.jobmanager;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
|
||||
class JobQueue {
|
||||
|
||||
private final Map<String, Job> activeGroupIds = new HashMap<>();
|
||||
private final LinkedList<Job> jobQueue = new LinkedList<>();
|
||||
|
||||
synchronized void onRequirementStatusChanged() {
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
synchronized void add(Job job) {
|
||||
jobQueue.add(job);
|
||||
processJobAddition(job);
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
synchronized void addAll(List<Job> jobs) {
|
||||
jobQueue.addAll(jobs);
|
||||
|
||||
for (Job job : jobs) {
|
||||
processJobAddition(job);
|
||||
}
|
||||
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
private void processJobAddition(@NonNull Job job) {
|
||||
if (isJobActive(job) && isGroupIdAvailable(job)) {
|
||||
setGroupIdUnavailable(job);
|
||||
} else if (!isGroupIdAvailable(job)) {
|
||||
Job blockingJob = activeGroupIds.get(job.getGroupId());
|
||||
blockingJob.resetRunStats();
|
||||
}
|
||||
}
|
||||
|
||||
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<Job> iterator = jobQueue.listIterator();
|
||||
while (iterator.hasNext()) {
|
||||
Job job = iterator.next();
|
||||
|
||||
if (job.isRequirementsMet() && isGroupIdAvailable(job)) {
|
||||
iterator.remove();
|
||||
setGroupIdUnavailable(job);
|
||||
return job;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isJobActive(@NonNull Job job) {
|
||||
return job.getRetryUntil() > 0 && job.getRunIteration() > 0;
|
||||
}
|
||||
|
||||
private boolean isGroupIdAvailable(@NonNull Job requester) {
|
||||
String groupId = requester.getGroupId();
|
||||
return groupId == null || !activeGroupIds.containsKey(groupId) || activeGroupIds.get(groupId).equals(requester);
|
||||
}
|
||||
|
||||
private void setGroupIdUnavailable(@NonNull Job job) {
|
||||
String groupId = job.getGroupId();
|
||||
if (groupId != null) {
|
||||
activeGroupIds.put(groupId, job);
|
||||
}
|
||||
}
|
||||
}
|
80
src/org/thoughtcrime/securesms/jobmanager/SafeData.java
Normal file
80
src/org/thoughtcrime/securesms/jobmanager/SafeData.java
Normal file
@ -0,0 +1,80 @@
|
||||
package org.thoughtcrime.securesms.jobmanager;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
/**
|
||||
* A wrapper around {@link Data} that does its best to throw an exception whenever a key isn't
|
||||
* present in the {@link Data} object.
|
||||
*/
|
||||
public class SafeData {
|
||||
|
||||
private final static int INVALID_INT = Integer.MIN_VALUE;
|
||||
private final static long INVALID_LONG = Long.MIN_VALUE;
|
||||
|
||||
private final Data data;
|
||||
|
||||
public SafeData(@NonNull Data data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public int getInt(@NonNull String key) {
|
||||
int value = data.getInt(key, INVALID_INT);
|
||||
|
||||
if (value == INVALID_INT) {
|
||||
throw new IllegalStateException("Missing key: " + key);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public long getLong(@NonNull String key) {
|
||||
long value = data.getLong(key, INVALID_LONG);
|
||||
|
||||
if (value == INVALID_LONG) {
|
||||
throw new IllegalStateException("Missing key: " + key);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public @NonNull String getString(@NonNull String key) {
|
||||
String value = data.getString(key);
|
||||
|
||||
if (value == null) {
|
||||
throw new IllegalStateException("Missing key: " + key);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public @Nullable String getNullableString(@NonNull String key) {
|
||||
return data.getString(key);
|
||||
}
|
||||
|
||||
public @NonNull String[] getStringArray(@NonNull String key) {
|
||||
String[] value = data.getStringArray(key);
|
||||
|
||||
if (value == null) {
|
||||
throw new IllegalStateException("Missing key: " + key);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public @NonNull long[] getLongArray(@NonNull String key) {
|
||||
long[] value = data.getLongArray(key);
|
||||
|
||||
if (value == null) {
|
||||
throw new IllegalStateException("Missing key: " + key);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean getBoolean(@NonNull String key, boolean defaultValue) {
|
||||
return data.getBoolean(key, defaultValue);
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -16,7 +16,6 @@
|
||||
*/
|
||||
package org.thoughtcrime.securesms.jobmanager.persistence;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
@ -24,7 +23,6 @@ import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.EncryptionKeys;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.dependencies.AggregateDependencyInjector;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -43,38 +41,18 @@ public class PersistentStorage {
|
||||
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;
|
||||
private final DatabaseHelper databaseHelper;
|
||||
private final JobSerializer jobSerializer;
|
||||
|
||||
public PersistentStorage(Context context, String name,
|
||||
JobSerializer serializer,
|
||||
AggregateDependencyInjector dependencyInjector)
|
||||
{
|
||||
public PersistentStorage(Context context, String name, JobSerializer serializer) {
|
||||
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<Job> getAllUnencrypted() {
|
||||
return getJobs(null, ENCRYPTED + " = 0");
|
||||
}
|
||||
|
||||
public List<Job> getAllEncrypted(EncryptionKeys keys) {
|
||||
return getJobs(keys, ENCRYPTED + " = 1");
|
||||
}
|
||||
|
||||
private List<Job> getJobs(EncryptionKeys keys, String where) {
|
||||
List<Job> results = new LinkedList<>();
|
||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||
@ -90,11 +68,6 @@ public class PersistentStorage {
|
||||
|
||||
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);
|
||||
|
@ -1,35 +0,0 @@
|
||||
package org.thoughtcrime.securesms.jobmanager.requirements;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BackoffReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = BackoffReceiver.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.i(TAG, "Received an alarm to retry a job with ID: " + intent.getAction());
|
||||
ApplicationContext.getInstance(context).getJobManager().onRequirementStatusChanged();
|
||||
}
|
||||
|
||||
public static void setUniqueAlarm(@NonNull Context context, long time) {
|
||||
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
||||
Intent intent = new Intent(context, BackoffReceiver.class);
|
||||
|
||||
intent.setAction(BuildConfig.APPLICATION_ID + UUID.randomUUID().toString());
|
||||
alarmManager.set(AlarmManager.RTC_WAKEUP, time, PendingIntent.getBroadcast(context, 0, intent, 0));
|
||||
|
||||
Log.i(TAG, "Set an alarm to retry a job in " + (time - System.currentTimeMillis()) + " ms with ID: " + intent.getAction());
|
||||
}
|
||||
}
|
@ -31,15 +31,6 @@ public class NetworkBackoffRequirement implements Requirement, ContextDependent
|
||||
|
||||
@Override
|
||||
public void onRetry(@NonNull Job job) {
|
||||
Log.i(TAG, "onRetry()");
|
||||
|
||||
if (!(new NetworkRequirement(context).isPresent())) {
|
||||
Log.i(TAG, "No network. Resetting run stats.");
|
||||
job.resetRunStats();
|
||||
return;
|
||||
}
|
||||
|
||||
BackoffReceiver.setUniqueAlarm(context, NetworkBackoffRequirement.calculateNextRunTime(job));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -48,9 +39,6 @@ public class NetworkBackoffRequirement implements Requirement, ContextDependent
|
||||
}
|
||||
|
||||
private static long calculateNextRunTime(@NonNull Job job) {
|
||||
long targetTime = job.getLastRunTime() + (long) (Math.pow(2, job.getRunIteration() - 1) * 1000);
|
||||
long furthestTime = System.currentTimeMillis() + MAX_WAIT;
|
||||
|
||||
return Math.min(targetTime, Math.min(furthestTime, job.getRetryUntil()));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
@ -15,8 +18,6 @@ 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;
|
||||
import org.thoughtcrime.securesms.util.AttachmentUtil;
|
||||
@ -36,24 +37,34 @@ import java.io.InputStream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class AttachmentDownloadJob extends MasterSecretJob implements InjectableType {
|
||||
private static final long serialVersionUID = 2L;
|
||||
private static final int MAX_ATTACHMENT_SIZE = 150 * 1024 * 1024;
|
||||
private static final String TAG = AttachmentDownloadJob.class.getSimpleName();
|
||||
|
||||
private static final String KEY_MESSAGE_ID = "message_id";
|
||||
private static final String KEY_PART_ROW_ID = "part_row_id";
|
||||
private static final String KEY_PAR_UNIQUE_ID = "part_unique_id";
|
||||
private static final String KEY_MANUAL = "part_manual";
|
||||
|
||||
@Inject transient SignalServiceMessageReceiver messageReceiver;
|
||||
|
||||
private final long messageId;
|
||||
private final long partRowId;
|
||||
private final long partUniqueId;
|
||||
private final boolean manual;
|
||||
private long messageId;
|
||||
private long partRowId;
|
||||
private long partUniqueId;
|
||||
private boolean manual;
|
||||
|
||||
public AttachmentDownloadJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public AttachmentDownloadJob(Context context, long messageId, AttachmentId attachmentId, boolean manual) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withGroupId(AttachmentDownloadJob.class.getCanonicalName())
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withPersistence()
|
||||
.withMasterSecretRequirement()
|
||||
.withNetworkRequirement()
|
||||
.create());
|
||||
|
||||
this.messageId = messageId;
|
||||
@ -62,6 +73,23 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
|
||||
this.manual = manual;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
messageId = data.getLong(KEY_MESSAGE_ID);
|
||||
partRowId = data.getLong(KEY_PART_ROW_ID);
|
||||
partUniqueId = data.getLong(KEY_PAR_UNIQUE_ID);
|
||||
manual = data.getBoolean(KEY_MANUAL, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putLong(KEY_MESSAGE_ID, messageId)
|
||||
.putLong(KEY_PART_ROW_ID, partRowId)
|
||||
.putLong(KEY_PAR_UNIQUE_ID, partUniqueId)
|
||||
.putBoolean(KEY_MANUAL, manual)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
Log.i(TAG, "onAdded() messageId: " + messageId + " partRowId: " + partRowId + " partUniqueId: " + partUniqueId + " manual: " + manual);
|
||||
|
@ -1,86 +0,0 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentId;
|
||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
||||
import org.thoughtcrime.securesms.crypto.AsymmetricMasterCipher;
|
||||
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.libsignal.InvalidMessageException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class AttachmentFileNameJob extends MasterSecretJob {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final long attachmentRowId;
|
||||
private final long attachmentUniqueId;
|
||||
private final String encryptedFileName;
|
||||
|
||||
public AttachmentFileNameJob(@NonNull Context context, @NonNull AsymmetricMasterSecret asymmetricMasterSecret,
|
||||
@NonNull DatabaseAttachment attachment, @NonNull IncomingMediaMessage message)
|
||||
{
|
||||
super(context, new JobParameters.Builder().withPersistence()
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.create());
|
||||
|
||||
this.attachmentRowId = attachment.getAttachmentId().getRowId();
|
||||
this.attachmentUniqueId = attachment.getAttachmentId().getUniqueId();
|
||||
this.encryptedFileName = getEncryptedFileName(asymmetricMasterSecret, attachment, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun(MasterSecret masterSecret) throws IOException, InvalidMessageException {
|
||||
if (encryptedFileName == null) return;
|
||||
|
||||
AttachmentId attachmentId = new AttachmentId(attachmentRowId, attachmentUniqueId);
|
||||
String plaintextFileName = new AsymmetricMasterCipher(MasterSecretUtil.getAsymmetricMasterSecret(context, masterSecret)).decryptBody(encryptedFileName);
|
||||
|
||||
DatabaseFactory.getAttachmentDatabase(context).updateAttachmentFileName(attachmentId, plaintextFileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onShouldRetryThrowable(Exception exception) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
|
||||
}
|
||||
|
||||
private @Nullable String getEncryptedFileName(@NonNull AsymmetricMasterSecret asymmetricMasterSecret,
|
||||
@NonNull DatabaseAttachment attachment,
|
||||
@NonNull IncomingMediaMessage mediaMessage)
|
||||
{
|
||||
for (Attachment messageAttachment : mediaMessage.getAttachments()) {
|
||||
if (mediaMessage.getAttachments().size() == 1 ||
|
||||
(messageAttachment.getDigest() != null && Arrays.equals(messageAttachment.getDigest(), attachment.getDigest())))
|
||||
{
|
||||
if (messageAttachment.getFileName() == null) return null;
|
||||
else return new AsymmetricMasterCipher(asymmetricMasterSecret).encryptBody(messageAttachment.getFileName());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -10,8 +10,7 @@ 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.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel;
|
||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||
@ -30,6 +29,8 @@ import java.io.InputStream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class AvatarDownloadJob extends MasterSecretJob implements InjectableType {
|
||||
|
||||
private static final int MAX_AVATAR_SIZE = 20 * 1024 * 1024;
|
||||
@ -37,22 +38,38 @@ public class AvatarDownloadJob extends MasterSecretJob implements InjectableType
|
||||
|
||||
private static final String TAG = AvatarDownloadJob.class.getSimpleName();
|
||||
|
||||
private static final String KEY_GROUP_ID = "group_id";
|
||||
|
||||
@Inject transient SignalServiceMessageReceiver receiver;
|
||||
|
||||
private final byte[] groupId;
|
||||
private byte[] groupId;
|
||||
|
||||
public AvatarDownloadJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public AvatarDownloadJob(Context context, @NonNull byte[] groupId) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withPersistence()
|
||||
.withMasterSecretRequirement()
|
||||
.withNetworkRequirement()
|
||||
.create());
|
||||
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
try {
|
||||
groupId = GroupUtil.getDecodedId(data.getString(KEY_GROUP_ID));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putString(KEY_GROUP_ID, GroupUtil.getEncodedId(groupId, false)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun(MasterSecret masterSecret) throws IOException {
|
||||
|
@ -1,13 +1,15 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.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.libsignal.InvalidKeyIdException;
|
||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||
import org.whispersystems.libsignal.state.SignedPreKeyStore;
|
||||
@ -24,6 +26,8 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
import static org.thoughtcrime.securesms.dependencies.AxolotlStorageModule.SignedPreKeyStoreFactory;
|
||||
|
||||
public class CleanPreKeysJob extends MasterSecretJob implements InjectableType {
|
||||
@ -35,17 +39,25 @@ public class CleanPreKeysJob extends MasterSecretJob implements InjectableType {
|
||||
@Inject transient SignalServiceAccountManager accountManager;
|
||||
@Inject transient SignedPreKeyStoreFactory signedPreKeyStoreFactory;
|
||||
|
||||
public CleanPreKeysJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public CleanPreKeysJob(Context context) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withGroupId(CleanPreKeysJob.class.getSimpleName())
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withMasterSecretRequirement()
|
||||
.withRetryCount(5)
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,14 +1,14 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
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.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.IdentityKeyPair;
|
||||
@ -20,6 +20,8 @@ import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class CreateSignedPreKeyJob extends MasterSecretJob implements InjectableType {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -28,17 +30,26 @@ public class CreateSignedPreKeyJob extends MasterSecretJob implements Injectable
|
||||
|
||||
@Inject transient SignalServiceAccountManager accountManager;
|
||||
|
||||
public CreateSignedPreKeyJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public CreateSignedPreKeyJob(Context context) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withNetworkRequirement()
|
||||
.withMasterSecretRequirement()
|
||||
.withGroupId(CreateSignedPreKeyJob.class.getSimpleName())
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun(MasterSecret masterSecret) throws IOException {
|
||||
|
@ -1,26 +1,36 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.PowerManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.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.signalservice.api.push.exceptions.PushNetworkException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class DirectoryRefreshJob extends ContextJob {
|
||||
|
||||
private static final String TAG = DirectoryRefreshJob.class.getSimpleName();
|
||||
|
||||
private static final String KEY_ADDRESS = "address";
|
||||
private static final String KEY_NOTIFY_OF_NEW_USERS = "notify_of_new_users";
|
||||
|
||||
@Nullable private transient Recipient recipient;
|
||||
private transient boolean notifyOfNewUsers;
|
||||
|
||||
public DirectoryRefreshJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public DirectoryRefreshJob(@NonNull Context context, boolean notifyOfNewUsers) {
|
||||
this(context, null, notifyOfNewUsers);
|
||||
}
|
||||
@ -31,7 +41,7 @@ public class DirectoryRefreshJob extends ContextJob {
|
||||
{
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withGroupId(DirectoryRefreshJob.class.getSimpleName())
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withNetworkRequirement()
|
||||
.create());
|
||||
|
||||
this.recipient = recipient;
|
||||
@ -39,23 +49,29 @@ public class DirectoryRefreshJob extends ContextJob {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
String serializedAddress = data.getNullableString(KEY_ADDRESS);
|
||||
Address address = serializedAddress != null ? Address.fromSerialized(serializedAddress) : null;
|
||||
|
||||
recipient = address != null ? Recipient.from(context, address, true) : null;
|
||||
notifyOfNewUsers = data.getBoolean(KEY_NOTIFY_OF_NEW_USERS, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putString(KEY_ADDRESS, recipient != null ? recipient.getAddress().serialize() : null)
|
||||
.putBoolean(KEY_NOTIFY_OF_NEW_USERS, notifyOfNewUsers)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException {
|
||||
Log.i(TAG, "DirectoryRefreshJob.onRun()");
|
||||
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Directory Refresh");
|
||||
|
||||
try {
|
||||
wakeLock.acquire();
|
||||
if (recipient == null) {
|
||||
DirectoryHelper.refreshDirectory(context, notifyOfNewUsers);
|
||||
} else {
|
||||
DirectoryHelper.refreshDirectoryFor(context, recipient);
|
||||
}
|
||||
} finally {
|
||||
if (wakeLock.isHeld()) wakeLock.release();
|
||||
if (recipient == null) {
|
||||
DirectoryHelper.refreshDirectory(context, notifyOfNewUsers);
|
||||
} else {
|
||||
DirectoryHelper.refreshDirectoryFor(context, recipient);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,10 @@ import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
@ -32,7 +35,6 @@ 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.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
@ -41,6 +43,8 @@ import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulRespons
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class GcmRefreshJob extends ContextJob implements InjectableType {
|
||||
|
||||
private static final String TAG = GcmRefreshJob.class.getSimpleName();
|
||||
@ -49,15 +53,27 @@ public class GcmRefreshJob extends ContextJob implements InjectableType {
|
||||
|
||||
@Inject transient SignalServiceAccountManager textSecureAccountManager;
|
||||
|
||||
public GcmRefreshJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public GcmRefreshJob(Context context) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withGroupId(GcmRefreshJob.class.getSimpleName())
|
||||
.withDuplicatesIgnored(true)
|
||||
.withNetworkRequirement()
|
||||
.withRetryCount(1)
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws Exception {
|
||||
|
@ -4,6 +4,8 @@ package org.thoughtcrime.securesms.jobs;
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
@ -24,21 +26,32 @@ import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class LocalBackupJob extends ContextJob {
|
||||
|
||||
private static final String TAG = LocalBackupJob.class.getSimpleName();
|
||||
|
||||
public LocalBackupJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public LocalBackupJob(@NonNull Context context) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withGroupId("__LOCAL_BACKUP__")
|
||||
.withWakeLock(true, 10, TimeUnit.SECONDS)
|
||||
.withDuplicatesIgnored(true)
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws NoExternalStorageException, IOException {
|
||||
|
@ -2,7 +2,10 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import com.google.android.mms.pdu_alt.CharacterSets;
|
||||
@ -20,8 +23,6 @@ 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;
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
||||
@ -45,7 +46,8 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class MmsDownloadJob extends MasterSecretJob {
|
||||
|
||||
@ -53,17 +55,23 @@ public class MmsDownloadJob extends MasterSecretJob {
|
||||
|
||||
private static final String TAG = MmsDownloadJob.class.getSimpleName();
|
||||
|
||||
private final long messageId;
|
||||
private final long threadId;
|
||||
private final boolean automatic;
|
||||
private static final String KEY_MESSAGE_ID = "message_id";
|
||||
private static final String KEY_THREAD_ID = "thread_id";
|
||||
private static final String KEY_AUTOMATIC = "automatic";
|
||||
|
||||
private long messageId;
|
||||
private long threadId;
|
||||
private boolean automatic;
|
||||
|
||||
public MmsDownloadJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public MmsDownloadJob(Context context, long messageId, long threadId, boolean automatic) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withMasterSecretRequirement()
|
||||
.withMasterSecretRequirement()
|
||||
.withGroupId("mms-operation")
|
||||
.withWakeLock(true, 30, TimeUnit.SECONDS)
|
||||
.create());
|
||||
|
||||
this.messageId = messageId;
|
||||
@ -71,6 +79,21 @@ public class MmsDownloadJob extends MasterSecretJob {
|
||||
this.automatic = automatic;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
messageId = data.getLong(KEY_MESSAGE_ID);
|
||||
threadId = data.getLong(KEY_THREAD_ID);
|
||||
automatic = data.getBoolean(KEY_AUTOMATIC, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putLong(KEY_MESSAGE_ID, messageId)
|
||||
.putLong(KEY_THREAD_ID, threadId)
|
||||
.putBoolean(KEY_AUTOMATIC, automatic)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
if (automatic && KeyCachingService.getMasterSecret(context) == null) {
|
||||
|
@ -1,7 +1,11 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.google.android.mms.pdu_alt.GenericPdu;
|
||||
@ -15,29 +19,51 @@ 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.Base64;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class MmsReceiveJob extends ContextJob {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TAG = MmsReceiveJob.class.getSimpleName();
|
||||
|
||||
private final byte[] data;
|
||||
private final int subscriptionId;
|
||||
private static final String KEY_DATA = "data";
|
||||
private static final String KEY_SUBSCRIPTION_ID = "subscription_id";
|
||||
|
||||
private byte[] data;
|
||||
private int subscriptionId;
|
||||
|
||||
public MmsReceiveJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public MmsReceiveJob(Context context, byte[] data, int subscriptionId) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withWakeLock(true)
|
||||
.withPersistence().create());
|
||||
super(context, JobParameters.newBuilder().create());
|
||||
|
||||
this.data = data;
|
||||
this.subscriptionId = subscriptionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
try {
|
||||
this.data = Base64.decode(data.getString(KEY_DATA));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
subscriptionId = data.getInt(KEY_SUBSCRIPTION_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putString(KEY_DATA, Base64.encodeBytes(data))
|
||||
.putInt(KEY_SUBSCRIPTION_ID, subscriptionId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,10 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
@ -27,8 +30,6 @@ 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;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
@ -49,28 +50,41 @@ import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class MmsSendJob extends SendJob {
|
||||
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private static final String TAG = MmsSendJob.class.getSimpleName();
|
||||
|
||||
private final long messageId;
|
||||
private static final String KEY_MESSAGE_ID = "message_id";
|
||||
|
||||
private long messageId;
|
||||
|
||||
public MmsSendJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public MmsSendJob(Context context, long messageId) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withGroupId("mms-operation")
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withPersistence()
|
||||
.withNetworkRequirement()
|
||||
.withMasterSecretRequirement()
|
||||
.withRetryCount(15)
|
||||
.create());
|
||||
|
||||
this.messageId = messageId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
Log.i(TAG, "onAdded() messageId: " + messageId);
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
messageId = data.getLong(KEY_MESSAGE_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putLong(KEY_MESSAGE_ID, messageId).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
@ -8,8 +9,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientReader;
|
||||
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.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
@ -24,6 +24,8 @@ import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class MultiDeviceBlockedUpdateJob extends MasterSecretJob implements InjectableType {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -32,15 +34,27 @@ public class MultiDeviceBlockedUpdateJob extends MasterSecretJob implements Inje
|
||||
|
||||
@Inject transient SignalServiceMessageSender messageSender;
|
||||
|
||||
public MultiDeviceBlockedUpdateJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public MultiDeviceBlockedUpdateJob(Context context) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withNetworkRequirement()
|
||||
.withMasterSecretRequirement()
|
||||
.withGroupId(MultiDeviceBlockedUpdateJob.class.getSimpleName())
|
||||
.withPersistence()
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun(MasterSecret masterSecret)
|
||||
throws IOException, UntrustedIdentityException
|
||||
@ -71,11 +85,6 @@ public class MultiDeviceBlockedUpdateJob extends MasterSecretJob implements Inje
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
|
||||
|
@ -20,8 +20,7 @@ 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.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
@ -50,6 +49,8 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class MultiDeviceContactUpdateJob extends MasterSecretJob implements InjectableType {
|
||||
|
||||
private static final long serialVersionUID = 2L;
|
||||
@ -58,12 +59,19 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
|
||||
|
||||
private static final long FULL_SYNC_TIME = TimeUnit.HOURS.toMillis(6);
|
||||
|
||||
private static final String KEY_ADDRESS = "address";
|
||||
private static final String KEY_FORCE_SYNC = "force_sync";
|
||||
|
||||
@Inject transient SignalServiceMessageSender messageSender;
|
||||
|
||||
private final @Nullable String address;
|
||||
private @Nullable String address;
|
||||
|
||||
private boolean forceSync;
|
||||
|
||||
public MultiDeviceContactUpdateJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public MultiDeviceContactUpdateJob(@NonNull Context context) {
|
||||
this(context, false);
|
||||
}
|
||||
@ -78,10 +86,9 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
|
||||
|
||||
public MultiDeviceContactUpdateJob(@NonNull Context context, @Nullable Address address, boolean forceSync) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withNetworkRequirement()
|
||||
.withMasterSecretRequirement()
|
||||
.withGroupId(MultiDeviceContactUpdateJob.class.getSimpleName())
|
||||
.withPersistence()
|
||||
.create());
|
||||
|
||||
this.forceSync = forceSync;
|
||||
@ -90,6 +97,19 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
|
||||
else this.address = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
address = data.getNullableString(KEY_ADDRESS);
|
||||
forceSync = data.getBoolean(KEY_FORCE_SYNC, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putString(KEY_ADDRESS, address)
|
||||
.putBoolean(KEY_FORCE_SYNC, forceSync)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun(MasterSecret masterSecret)
|
||||
throws IOException, UntrustedIdentityException, NetworkException
|
||||
@ -201,11 +221,6 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
@ -8,12 +9,11 @@ import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
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;
|
||||
@ -34,6 +34,8 @@ import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class MultiDeviceGroupUpdateJob extends MasterSecretJob implements InjectableType {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -41,15 +43,27 @@ public class MultiDeviceGroupUpdateJob extends MasterSecretJob implements Inject
|
||||
|
||||
@Inject transient SignalServiceMessageSender messageSender;
|
||||
|
||||
public MultiDeviceGroupUpdateJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public MultiDeviceGroupUpdateJob(Context context) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withNetworkRequirement()
|
||||
.withMasterSecretRequirement()
|
||||
.withGroupId(MultiDeviceGroupUpdateJob.class.getSimpleName())
|
||||
.withPersistence()
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun(MasterSecret masterSecret) throws Exception {
|
||||
File contactDataFile = createTempFile("multidevice-contact-update");
|
||||
@ -102,11 +116,6 @@ public class MultiDeviceGroupUpdateJob extends MasterSecretJob implements Inject
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
|
||||
|
@ -2,13 +2,15 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.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.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
@ -27,6 +29,8 @@ import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class MultiDeviceProfileKeyUpdateJob extends MasterSecretJob implements InjectableType {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -34,14 +38,26 @@ public class MultiDeviceProfileKeyUpdateJob extends MasterSecretJob implements I
|
||||
|
||||
@Inject transient SignalServiceMessageSender messageSender;
|
||||
|
||||
public MultiDeviceProfileKeyUpdateJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public MultiDeviceProfileKeyUpdateJob(Context context) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withPersistence()
|
||||
.withNetworkRequirement()
|
||||
.withGroupId(MultiDeviceProfileKeyUpdateJob.class.getSimpleName())
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun(MasterSecret masterSecret) throws IOException, UntrustedIdentityException {
|
||||
if (!TextSecurePreferences.isMultiDevice(getContext())) {
|
||||
@ -79,11 +95,6 @@ public class MultiDeviceProfileKeyUpdateJob extends MasterSecretJob implements I
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
Log.w(TAG, "Profile key sync failed!");
|
||||
|
@ -2,10 +2,11 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobParameters;
|
||||
import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
@ -18,28 +19,42 @@ import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class MultiDeviceReadReceiptUpdateJob extends ContextJob implements InjectableType {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TAG = MultiDeviceReadReceiptUpdateJob.class.getSimpleName();
|
||||
|
||||
private static final String KEY_ENABLED = "enabled";
|
||||
|
||||
@Inject transient SignalServiceMessageSender messageSender;
|
||||
|
||||
private final boolean enabled;
|
||||
private boolean enabled;
|
||||
|
||||
public MultiDeviceReadReceiptUpdateJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public MultiDeviceReadReceiptUpdateJob(Context context, boolean enabled) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withGroupId("__MULTI_DEVICE_READ_RECEIPT_UPDATE_JOB__")
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withNetworkRequirement()
|
||||
.create());
|
||||
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
enabled = data.getBoolean(KEY_ENABLED, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putBoolean(KEY_ENABLED, enabled).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException, UntrustedIdentityException {
|
||||
|
@ -1,14 +1,18 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.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.JsonUtils;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
@ -18,25 +22,33 @@ import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class MultiDeviceReadUpdateJob extends MasterSecretJob implements InjectableType {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String TAG = MultiDeviceReadUpdateJob.class.getSimpleName();
|
||||
|
||||
private final List<SerializableSyncMessageId> messageIds;
|
||||
private static final String KEY_MESSAGE_IDS = "message_ids";
|
||||
|
||||
private List<SerializableSyncMessageId> messageIds;
|
||||
|
||||
@Inject transient SignalServiceMessageSender messageSender;
|
||||
|
||||
public MultiDeviceReadUpdateJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public MultiDeviceReadUpdateJob(Context context, List<SyncMessageId> messageIds) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withPersistence()
|
||||
.withNetworkRequirement()
|
||||
.withMasterSecretRequirement()
|
||||
.create());
|
||||
|
||||
this.messageIds = new LinkedList<>();
|
||||
@ -46,6 +58,34 @@ public class MultiDeviceReadUpdateJob extends MasterSecretJob implements Injecta
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
String[] ids = data.getStringArray(KEY_MESSAGE_IDS);
|
||||
|
||||
messageIds = new ArrayList<>(ids.length);
|
||||
for (String id : ids) {
|
||||
try {
|
||||
messageIds.add(JsonUtils.fromJson(id, SerializableSyncMessageId.class));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
String[] ids = new String[messageIds.size()];
|
||||
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
try {
|
||||
ids[i] = JsonUtils.toJson(messageIds.get(i));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
return dataBuilder.putStringArray(KEY_MESSAGE_IDS, ids).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun(MasterSecret masterSecret) throws IOException, UntrustedIdentityException {
|
||||
@ -68,11 +108,6 @@ public class MultiDeviceReadUpdateJob extends MasterSecretJob implements Injecta
|
||||
return exception instanceof PushNetworkException;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
|
||||
@ -82,10 +117,13 @@ public class MultiDeviceReadUpdateJob extends MasterSecretJob implements Injecta
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonProperty
|
||||
private final String sender;
|
||||
|
||||
@JsonProperty
|
||||
private final long timestamp;
|
||||
|
||||
private SerializableSyncMessageId(String sender, long timestamp) {
|
||||
private SerializableSyncMessageId(@JsonProperty("sender") String sender, @JsonProperty("timestamp") long timestamp) {
|
||||
this.sender = sender;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
@ -2,13 +2,16 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.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.Base64;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.IdentityKey;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
@ -22,24 +25,34 @@ import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class MultiDeviceVerifiedUpdateJob extends ContextJob implements InjectableType {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TAG = MultiDeviceVerifiedUpdateJob.class.getSimpleName();
|
||||
|
||||
private static final String KEY_DESTINATION = "destination";
|
||||
private static final String KEY_IDENTITY_KEY = "identity_key";
|
||||
private static final String KEY_VERIFIED_STATUS = "verified_status";
|
||||
private static final String KEY_TIMESTAMP = "timestamp";
|
||||
|
||||
@Inject
|
||||
transient SignalServiceMessageSender messageSender;
|
||||
|
||||
private final String destination;
|
||||
private final byte[] identityKey;
|
||||
private final VerifiedStatus verifiedStatus;
|
||||
private final long timestamp;
|
||||
private String destination;
|
||||
private byte[] identityKey;
|
||||
private VerifiedStatus verifiedStatus;
|
||||
private long timestamp;
|
||||
|
||||
public MultiDeviceVerifiedUpdateJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public MultiDeviceVerifiedUpdateJob(Context context, Address destination, IdentityKey identityKey, VerifiedStatus verifiedStatus) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withPersistence()
|
||||
.withNetworkRequirement()
|
||||
.withGroupId("__MULTI_DEVICE_VERIFIED_UPDATE__")
|
||||
.create());
|
||||
|
||||
@ -49,6 +62,28 @@ public class MultiDeviceVerifiedUpdateJob extends ContextJob implements Injectab
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
destination = data.getString(KEY_DESTINATION);
|
||||
verifiedStatus = VerifiedStatus.forState(data.getInt(KEY_VERIFIED_STATUS));
|
||||
timestamp = data.getLong(KEY_TIMESTAMP);
|
||||
|
||||
try {
|
||||
identityKey = Base64.decode(data.getString(KEY_IDENTITY_KEY));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putString(KEY_DESTINATION, destination)
|
||||
.putString(KEY_IDENTITY_KEY, Base64.encodeBytes(identityKey))
|
||||
.putInt(KEY_VERIFIED_STATUS, verifiedStatus.toInt())
|
||||
.putLong(KEY_TIMESTAMP, timestamp)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException, UntrustedIdentityException {
|
||||
try {
|
||||
@ -90,11 +125,6 @@ public class MultiDeviceVerifiedUpdateJob extends ContextJob implements Injectab
|
||||
return exception instanceof PushNetworkException;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.JobParameters;
|
||||
@ -10,12 +13,20 @@ import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class PushContentReceiveJob extends PushReceivedJob {
|
||||
|
||||
private static final long serialVersionUID = 5685475456901715638L;
|
||||
private static final String TAG = PushContentReceiveJob.class.getSimpleName();
|
||||
|
||||
private final String data;
|
||||
private static final String KEY_DATA = "data";
|
||||
|
||||
private String data;
|
||||
|
||||
public PushContentReceiveJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public PushContentReceiveJob(Context context) {
|
||||
super(context, JobParameters.newBuilder().create());
|
||||
@ -23,16 +34,19 @@ public class PushContentReceiveJob extends PushReceivedJob {
|
||||
}
|
||||
|
||||
public PushContentReceiveJob(Context context, String data) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withWakeLock(true)
|
||||
.create());
|
||||
|
||||
super(context, JobParameters.newBuilder().create());
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
this.data = data.getNullableString(KEY_DATA);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putString(KEY_DATA, data).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() {
|
||||
|
@ -7,6 +7,8 @@ import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationManagerCompat;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
@ -98,7 +100,8 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class PushDecryptJob extends ContextJob {
|
||||
|
||||
@ -106,8 +109,15 @@ public class PushDecryptJob extends ContextJob {
|
||||
|
||||
public static final String TAG = PushDecryptJob.class.getSimpleName();
|
||||
|
||||
private final long messageId;
|
||||
private final long smsMessageId;
|
||||
private static final String KEY_MESSAGE_ID = "message_id";
|
||||
private static final String KEY_SMS_MESSAGE_ID = "sms_message_id";
|
||||
|
||||
private long messageId;
|
||||
private long smsMessageId;
|
||||
|
||||
public PushDecryptJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public PushDecryptJob(Context context, long pushMessageId) {
|
||||
this(context, pushMessageId, -1);
|
||||
@ -115,16 +125,24 @@ public class PushDecryptJob extends ContextJob {
|
||||
|
||||
public PushDecryptJob(Context context, long pushMessageId, long smsMessageId) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withGroupId("__PUSH_DECRYPT_JOB__")
|
||||
.withWakeLock(true, 5, TimeUnit.SECONDS)
|
||||
.create());
|
||||
this.messageId = pushMessageId;
|
||||
this.smsMessageId = smsMessageId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
messageId = data.getLong(KEY_MESSAGE_ID);
|
||||
smsMessageId = data.getLong(KEY_SMS_MESSAGE_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putLong(KEY_MESSAGE_ID, messageId)
|
||||
.putLong(KEY_SMS_MESSAGE_ID, smsMessageId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws NoSuchMessageException {
|
||||
|
@ -16,8 +16,7 @@ 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.NetworkBackoffRequirement;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
@ -48,6 +47,8 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -56,16 +57,22 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
@Inject transient SignalServiceMessageSender messageSender;
|
||||
|
||||
private final long messageId;
|
||||
private final long filterRecipientId; // Deprecated
|
||||
private final String filterAddress;
|
||||
private static final String KEY_MESSAGE_ID = "message_id";
|
||||
private static final String KEY_FILTER_ADDRESS = "filter_address";
|
||||
|
||||
private long messageId;
|
||||
private long filterRecipientId; // Deprecated
|
||||
private String filterAddress;
|
||||
|
||||
public PushGroupSendJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public PushGroupSendJob(Context context, long messageId, @NonNull Address destination, @Nullable Address filterAddress) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withGroupId(destination.toGroupString())
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withRequirement(new NetworkBackoffRequirement(context))
|
||||
.withMasterSecretRequirement()
|
||||
.withNetworkRequirement()
|
||||
.withRetryDuration(TimeUnit.DAYS.toMillis(1))
|
||||
.create());
|
||||
|
||||
@ -75,8 +82,16 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
Log.i(TAG, "onAdded() messageId: " + messageId);
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
messageId = data.getLong(KEY_MESSAGE_ID);
|
||||
filterAddress = data.getNullableString(KEY_FILTER_ADDRESS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putLong(KEY_MESSAGE_ID, messageId)
|
||||
.putString(KEY_FILTER_ADDRESS, filterAddress)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,6 +2,9 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
@ -10,7 +13,6 @@ 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.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
@ -28,26 +30,34 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class PushGroupUpdateJob extends ContextJob implements InjectableType {
|
||||
|
||||
private static final String TAG = PushGroupUpdateJob.class.getSimpleName();
|
||||
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private static final String KEY_SOURCE = "source";
|
||||
private static final String KEY_GROUP_ID = "group_id";
|
||||
|
||||
@Inject transient SignalServiceMessageSender messageSender;
|
||||
|
||||
private final String source;
|
||||
private final byte[] groupId;
|
||||
private String source;
|
||||
private byte[] groupId;
|
||||
|
||||
public PushGroupUpdateJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public PushGroupUpdateJob(Context context, String source, byte[] groupId) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withRetryCount(50)
|
||||
.withNetworkRequirement()
|
||||
.withRetryDuration(TimeUnit.DAYS.toMillis(1))
|
||||
.create());
|
||||
|
||||
this.source = source;
|
||||
@ -55,7 +65,21 @@ public class PushGroupUpdateJob extends ContextJob implements InjectableType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
source = data.getString(KEY_SOURCE);
|
||||
try {
|
||||
groupId = GroupUtil.getDecodedId(data.getString(KEY_GROUP_ID));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putString(KEY_SOURCE, source)
|
||||
.putString(KEY_GROUP_ID, GroupUtil.getEncodedId(groupId, false))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException, UntrustedIdentityException {
|
||||
|
@ -1,6 +1,9 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
@ -32,24 +35,37 @@ import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TAG = PushMediaSendJob.class.getSimpleName();
|
||||
|
||||
private static final String KEY_MESSAGE_ID = "message_id";
|
||||
|
||||
@Inject transient SignalServiceMessageSender messageSender;
|
||||
|
||||
private final long messageId;
|
||||
private long messageId;
|
||||
|
||||
public PushMediaSendJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public PushMediaSendJob(Context context, long messageId, Address destination) {
|
||||
super(context, constructParameters(context, destination));
|
||||
super(context, constructParameters(destination));
|
||||
this.messageId = messageId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
Log.i(TAG, "onAdded() messageId: " + messageId);
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
messageId = data.getLong(KEY_MESSAGE_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putLong(KEY_MESSAGE_ID, messageId).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,35 +1,47 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobParameters;
|
||||
import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class PushNotificationReceiveJob extends PushReceivedJob implements InjectableType {
|
||||
|
||||
private static final String TAG = PushNotificationReceiveJob.class.getSimpleName();
|
||||
|
||||
@Inject transient SignalServiceMessageReceiver receiver;
|
||||
|
||||
public PushNotificationReceiveJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public PushNotificationReceiveJob(Context context) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withNetworkRequirement()
|
||||
.withGroupId("__notification_received")
|
||||
.withWakeLock(true, 30, TimeUnit.SECONDS).create());
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException {
|
||||
|
@ -15,8 +15,6 @@ 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.NetworkBackoffRequirement;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
@ -49,12 +47,11 @@ public abstract class PushSendJob extends SendJob {
|
||||
super(context, parameters);
|
||||
}
|
||||
|
||||
protected static JobParameters constructParameters(Context context, Address destination) {
|
||||
protected static JobParameters constructParameters(Address destination) {
|
||||
JobParameters.Builder builder = JobParameters.newBuilder();
|
||||
builder.withPersistence();
|
||||
builder.withGroupId(destination.serialize());
|
||||
builder.withRequirement(new MasterSecretRequirement(context));
|
||||
builder.withRequirement(new NetworkBackoffRequirement(context));
|
||||
builder.withMasterSecretRequirement();
|
||||
builder.withNetworkRequirement();
|
||||
builder.withRetryDuration(TimeUnit.DAYS.toMillis(1));
|
||||
|
||||
return builder.create();
|
||||
@ -80,7 +77,7 @@ public abstract class PushSendJob extends SendJob {
|
||||
super.onRetry();
|
||||
Log.i(TAG, "onRetry()");
|
||||
|
||||
if (getRunIteration() > 1) {
|
||||
if (getRunAttemptCount() > 1) {
|
||||
Log.i(TAG, "Scheduling service outage detection job.");
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new ServiceOutageDetectionJob(context));
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
@ -26,21 +29,39 @@ import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TAG = PushTextSendJob.class.getSimpleName();
|
||||
|
||||
private static final String KEY_MESSAGE_ID = "message_id";
|
||||
|
||||
@Inject transient SignalServiceMessageSender messageSender;
|
||||
|
||||
private final long messageId;
|
||||
private long messageId;
|
||||
|
||||
public PushTextSendJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public PushTextSendJob(Context context, long messageId, Address destination) {
|
||||
super(context, constructParameters(context, destination));
|
||||
super(context, constructParameters(destination));
|
||||
this.messageId = messageId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
messageId = data.getLong(KEY_MESSAGE_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putLong(KEY_MESSAGE_ID, messageId).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
Log.i(TAG, "onAdded() messageId: " + messageId);
|
||||
|
@ -1,20 +1,23 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.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.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NetworkFailureException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class RefreshAttributesJob extends ContextJob implements InjectableType {
|
||||
|
||||
public static final long serialVersionUID = 1L;
|
||||
@ -23,17 +26,25 @@ public class RefreshAttributesJob extends ContextJob implements InjectableType {
|
||||
|
||||
@Inject transient SignalServiceAccountManager signalAccountManager;
|
||||
|
||||
public RefreshAttributesJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public RefreshAttributesJob(Context context) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withWakeLock(true, 30, TimeUnit.SECONDS)
|
||||
.withNetworkRequirement()
|
||||
.withGroupId(RefreshAttributesJob.class.getName())
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
@ -8,8 +9,7 @@ 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.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.IdentityKeyPair;
|
||||
@ -24,6 +24,8 @@ import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class RefreshPreKeysJob extends MasterSecretJob implements InjectableType {
|
||||
|
||||
private static final String TAG = RefreshPreKeysJob.class.getSimpleName();
|
||||
@ -32,18 +34,26 @@ public class RefreshPreKeysJob extends MasterSecretJob implements InjectableType
|
||||
|
||||
@Inject transient SignalServiceAccountManager accountManager;
|
||||
|
||||
public RefreshPreKeysJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public RefreshPreKeysJob(Context context) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withGroupId(RefreshPreKeysJob.class.getSimpleName())
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withNetworkRequirement()
|
||||
.withMasterSecretRequirement()
|
||||
.withRetryCount(5)
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -5,7 +5,8 @@ import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobParameters;
|
||||
import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
@ -18,21 +19,29 @@ import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class RequestGroupInfoJob extends ContextJob implements InjectableType {
|
||||
|
||||
private static final String TAG = RequestGroupInfoJob.class.getSimpleName();
|
||||
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private static final String KEY_SOURCE = "source";
|
||||
private static final String KEY_GROUP_ID = "group_id";
|
||||
|
||||
@Inject transient SignalServiceMessageSender messageSender;
|
||||
|
||||
private final String source;
|
||||
private final byte[] groupId;
|
||||
private String source;
|
||||
private byte[] groupId;
|
||||
|
||||
public RequestGroupInfoJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public RequestGroupInfoJob(@NonNull Context context, @NonNull String source, @NonNull byte[] groupId) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withPersistence()
|
||||
.withNetworkRequirement()
|
||||
.withRetryCount(50)
|
||||
.create());
|
||||
|
||||
@ -41,7 +50,21 @@ public class RequestGroupInfoJob extends ContextJob implements InjectableType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
source = data.getString(KEY_SOURCE);
|
||||
try {
|
||||
groupId = GroupUtil.getDecodedId(data.getString(KEY_GROUP_ID));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putString(KEY_SOURCE, source)
|
||||
.putString(KEY_GROUP_ID, GroupUtil.getEncodedId(groupId, false))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException, UntrustedIdentityException {
|
||||
|
@ -2,14 +2,17 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.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;
|
||||
@ -23,21 +26,31 @@ import java.io.InputStream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class RetrieveProfileAvatarJob extends ContextJob implements InjectableType {
|
||||
|
||||
private static final String TAG = RetrieveProfileAvatarJob.class.getSimpleName();
|
||||
|
||||
private static final int MAX_PROFILE_SIZE_BYTES = 20 * 1024 * 1024;
|
||||
|
||||
private static final String KEY_PROFILE_AVATAR = "profile_avatar";
|
||||
private static final String KEY_ADDRESS = "address";
|
||||
|
||||
@Inject SignalServiceMessageReceiver receiver;
|
||||
|
||||
private final String profileAvatar;
|
||||
private final Recipient recipient;
|
||||
private String profileAvatar;
|
||||
private Recipient recipient;
|
||||
|
||||
public RetrieveProfileAvatarJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public RetrieveProfileAvatarJob(Context context, Recipient recipient, String profileAvatar) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withGroupId(RetrieveProfileAvatarJob.class.getSimpleName() + recipient.getAddress().serialize())
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withDuplicatesIgnored(true)
|
||||
.withNetworkRequirement()
|
||||
.create());
|
||||
|
||||
this.recipient = recipient;
|
||||
@ -45,7 +58,17 @@ public class RetrieveProfileAvatarJob extends ContextJob implements InjectableTy
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
profileAvatar = data.getString(KEY_PROFILE_AVATAR);
|
||||
recipient = Recipient.from(context, Address.fromSerialized(data.getString(KEY_ADDRESS)), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putString(KEY_PROFILE_AVATAR, profileAvatar)
|
||||
.putString(KEY_ADDRESS, recipient.getAddress().serialize())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException {
|
||||
|
@ -4,6 +4,9 @@ package org.thoughtcrime.securesms.jobs;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
@ -29,16 +32,25 @@ import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class RetrieveProfileJob extends ContextJob implements InjectableType {
|
||||
|
||||
private static final String TAG = RetrieveProfileJob.class.getSimpleName();
|
||||
|
||||
private static final String KEY_ADDRESS = "address";
|
||||
|
||||
@Inject transient SignalServiceMessageReceiver receiver;
|
||||
|
||||
private final Recipient recipient;
|
||||
private Recipient recipient;
|
||||
|
||||
public RetrieveProfileJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public RetrieveProfileJob(Context context, Recipient recipient) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withNetworkRequirement()
|
||||
.withRetryCount(3)
|
||||
.create());
|
||||
|
||||
@ -46,7 +58,14 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
recipient = Recipient.from(context, Address.fromSerialized(data.getString(KEY_ADDRESS)), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putString(KEY_ADDRESS, recipient.getAddress().serialize()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException, InvalidKeyException {
|
||||
|
@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
@ -9,8 +10,7 @@ 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.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.IdentityKeyPair;
|
||||
@ -20,23 +20,33 @@ import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class RotateSignedPreKeyJob extends MasterSecretJob implements InjectableType {
|
||||
|
||||
private static final String TAG = RotateSignedPreKeyJob.class.getName();
|
||||
|
||||
@Inject transient SignalServiceAccountManager accountManager;
|
||||
|
||||
public RotateSignedPreKeyJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public RotateSignedPreKeyJob(Context context) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withNetworkRequirement()
|
||||
.withMasterSecretRequirement()
|
||||
.withRetryCount(5)
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,11 +2,12 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
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.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
@ -16,26 +17,36 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class SendReadReceiptJob extends ContextJob implements InjectableType {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TAG = SendReadReceiptJob.class.getSimpleName();
|
||||
|
||||
private static final String KEY_ADDRESS = "address";
|
||||
private static final String KEY_MESSAGE_IDS = "message_ids";
|
||||
private static final String KEY_TIMESTAMP = "timestamp";
|
||||
|
||||
@Inject transient SignalServiceMessageSender messageSender;
|
||||
|
||||
private final String address;
|
||||
private final List<Long> messageIds;
|
||||
private final long timestamp;
|
||||
private String address;
|
||||
private List<Long> messageIds;
|
||||
private long timestamp;
|
||||
|
||||
public SendReadReceiptJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public SendReadReceiptJob(Context context, Address address, List<Long> messageIds) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withPersistence()
|
||||
.withNetworkRequirement()
|
||||
.create());
|
||||
|
||||
this.address = address.serialize();
|
||||
@ -44,7 +55,29 @@ public class SendReadReceiptJob extends ContextJob implements InjectableType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
address = data.getString(KEY_ADDRESS);
|
||||
timestamp = data.getLong(KEY_TIMESTAMP);
|
||||
|
||||
long[] ids = data.getLongArray(KEY_MESSAGE_IDS);
|
||||
messageIds = new ArrayList<>(ids.length);
|
||||
for (long id : ids) {
|
||||
messageIds.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
long[] ids = new long[messageIds.size()];
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
ids[i] = messageIds.get(i);
|
||||
}
|
||||
|
||||
return dataBuilder.putString(KEY_ADDRESS, address)
|
||||
.putLongArray(KEY_MESSAGE_IDS, ids)
|
||||
.putLong(KEY_TIMESTAMP, timestamp)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException, UntrustedIdentityException {
|
||||
|
@ -1,12 +1,13 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
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.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
@ -14,6 +15,8 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class ServiceOutageDetectionJob extends ContextJob {
|
||||
|
||||
private static final String TAG = ServiceOutageDetectionJob.class.getSimpleName();
|
||||
@ -22,16 +25,26 @@ public class ServiceOutageDetectionJob extends ContextJob {
|
||||
private static final String IP_FAILURE = "127.0.0.2";
|
||||
private static final long CHECK_TIME = 1000 * 60;
|
||||
|
||||
public ServiceOutageDetectionJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public ServiceOutageDetectionJob(Context context) {
|
||||
super(context, new JobParameters.Builder()
|
||||
.withGroupId(ServiceOutageDetectionJob.class.getSimpleName())
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withDuplicatesIgnored(true)
|
||||
.withNetworkRequirement()
|
||||
.withRetryCount(5)
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4,36 +4,47 @@ import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.telephony.SmsMessage;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
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.Base64;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class SmsReceiveJob extends ContextJob {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TAG = SmsReceiveJob.class.getSimpleName();
|
||||
|
||||
private final @Nullable Object[] pdus;
|
||||
private final int subscriptionId;
|
||||
private static final String KEY_PDUS = "pdus";
|
||||
private static final String KEY_SUBSCRIPTION_ID = "subscription_id";
|
||||
|
||||
private @Nullable Object[] pdus;
|
||||
|
||||
private int subscriptionId;
|
||||
|
||||
public SmsReceiveJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public SmsReceiveJob(@NonNull Context context, @Nullable Object[] pdus, int subscriptionId) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withWakeLock(true)
|
||||
.withRequirement(new SqlCipherMigrationRequirement(context))
|
||||
.withSqlCipherRequirement()
|
||||
.create());
|
||||
|
||||
this.pdus = pdus;
|
||||
@ -41,7 +52,31 @@ public class SmsReceiveJob extends ContextJob {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
String[] encoded = data.getStringArray(KEY_PDUS);
|
||||
pdus = new Object[encoded.length];
|
||||
try {
|
||||
for (int i = 0; i < encoded.length; i++) {
|
||||
pdus[i] = Base64.decode(encoded[i]);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
subscriptionId = data.getInt(KEY_SUBSCRIPTION_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
String[] encoded = new String[pdus.length];
|
||||
for (int i = 0; i < pdus.length; i++) {
|
||||
encoded[i] = Base64.encodeBytes((byte[]) pdus[i]);
|
||||
}
|
||||
|
||||
return dataBuilder.putStringArray(KEY_PDUS, encoded)
|
||||
.putInt(KEY_SUBSCRIPTION_ID, subscriptionId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws MigrationPendingException {
|
||||
|
@ -5,8 +5,11 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.telephony.PhoneNumberUtils;
|
||||
import android.telephony.SmsManager;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
@ -14,9 +17,6 @@ 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.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.NetworkOrServiceRequirement;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.ServiceRequirement;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.SmsDeliveryListener;
|
||||
@ -27,18 +27,35 @@ import org.thoughtcrime.securesms.jobmanager.JobParameters;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import androidx.work.Data;
|
||||
|
||||
public class SmsSendJob extends SendJob {
|
||||
|
||||
private static final long serialVersionUID = -5118520036244759718L;
|
||||
private static final String TAG = SmsSendJob.class.getSimpleName();
|
||||
private static final String KEY_MESSAGE_ID = "message_id";
|
||||
|
||||
private final long messageId;
|
||||
private long messageId;
|
||||
|
||||
public SmsSendJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public SmsSendJob(Context context, long messageId, String name) {
|
||||
super(context, constructParameters(context, name));
|
||||
super(context, constructParameters(name));
|
||||
this.messageId = messageId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
messageId = data.getLong(KEY_MESSAGE_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putLong(KEY_MESSAGE_ID, messageId).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
Log.i(TAG, "onAdded() messageId: " + messageId);
|
||||
@ -190,19 +207,11 @@ public class SmsSendJob extends SendJob {
|
||||
}
|
||||
}
|
||||
|
||||
private static JobParameters constructParameters(Context context, String name) {
|
||||
private static JobParameters constructParameters(String name) {
|
||||
JobParameters.Builder builder = JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withMasterSecretRequirement()
|
||||
.withRetryCount(15)
|
||||
.withGroupId(name);
|
||||
|
||||
if (TextSecurePreferences.isWifiSmsEnabled(context)) {
|
||||
builder.withRequirement(new NetworkOrServiceRequirement(context));
|
||||
} else {
|
||||
builder.withRequirement(new ServiceRequirement(context));
|
||||
}
|
||||
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,10 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.telephony.SmsManager;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
@ -12,23 +15,31 @@ 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 androidx.work.Data;
|
||||
|
||||
public class SmsSentJob extends MasterSecretJob {
|
||||
|
||||
private static final long serialVersionUID = -2624694558755317560L;
|
||||
private static final String TAG = SmsSentJob.class.getSimpleName();
|
||||
|
||||
private final long messageId;
|
||||
private final String action;
|
||||
private final int result;
|
||||
private static final String KEY_MESSAGE_ID = "message_id";
|
||||
private static final String KEY_ACTION = "action";
|
||||
private static final String KEY_RESULT = "result";
|
||||
|
||||
private long messageId;
|
||||
private String action;
|
||||
private int result;
|
||||
|
||||
public SmsSentJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public SmsSentJob(Context context, long messageId, String action, int result) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withMasterSecretRequirement()
|
||||
.create());
|
||||
|
||||
this.messageId = messageId;
|
||||
@ -37,8 +48,18 @@ public class SmsSentJob extends MasterSecretJob {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
messageId = data.getLong(KEY_MESSAGE_ID);
|
||||
action = data.getString(KEY_ACTION);
|
||||
result = data.getInt(KEY_RESULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putLong(KEY_MESSAGE_ID, messageId)
|
||||
.putString(KEY_ACTION, action)
|
||||
.putInt(KEY_RESULT, result)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,29 +17,42 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobParameters;
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
public class TrimThreadJob extends Job {
|
||||
import androidx.work.Data;
|
||||
|
||||
public class TrimThreadJob extends ContextJob {
|
||||
|
||||
private static final String TAG = TrimThreadJob.class.getSimpleName();
|
||||
|
||||
private final Context context;
|
||||
private final long threadId;
|
||||
private static final String KEY_THREAD_ID = "thread_id";
|
||||
|
||||
private long threadId;
|
||||
|
||||
public TrimThreadJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public TrimThreadJob(Context context, long threadId) {
|
||||
super(JobParameters.newBuilder().withGroupId(TrimThreadJob.class.getSimpleName()).create());
|
||||
super(context, JobParameters.newBuilder().withGroupId(TrimThreadJob.class.getSimpleName()).create());
|
||||
this.context = context;
|
||||
this.threadId = threadId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
threadId = data.getLong(KEY_THREAD_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.putLong(KEY_THREAD_ID, threadId).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -9,14 +9,16 @@ import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||
import org.thoughtcrime.securesms.logging.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;
|
||||
@ -26,8 +28,8 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import androidx.work.Data;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
@ -36,17 +38,26 @@ public class UpdateApkJob extends ContextJob {
|
||||
|
||||
private static final String TAG = UpdateApkJob.class.getSimpleName();
|
||||
|
||||
public UpdateApkJob() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public UpdateApkJob(Context context) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withGroupId(UpdateApkJob.class.getSimpleName())
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withWakeLock(true, 30, TimeUnit.SECONDS)
|
||||
.withNetworkRequirement()
|
||||
.withRetryCount(2)
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {}
|
||||
protected void initialize(@NonNull SafeData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
|
||||
return dataBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException, PackageManager.NameNotFoundException {
|
||||
|
Loading…
Reference in New Issue
Block a user