Switch to using our own JobManager.

// FREEBIE
This commit is contained in:
Moxie Marlinspike
2014-08-04 16:15:13 -07:00
parent 73d896f378
commit b308996885
12 changed files with 184 additions and 152 deletions

View File

@@ -19,14 +19,12 @@ package org.thoughtcrime.securesms;
import android.app.Application;
import android.content.Context;
import com.path.android.jobqueue.JobManager;
import com.path.android.jobqueue.config.Configuration;
import org.thoughtcrime.securesms.crypto.PRNGFixes;
import org.thoughtcrime.securesms.jobs.ContextInjector;
import org.thoughtcrime.securesms.jobs.EncryptingJobSerializer;
import org.thoughtcrime.securesms.jobs.GcmRefreshJob;
import org.thoughtcrime.securesms.jobs.JobLogger;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.jobqueue.JobManager;
import org.whispersystems.jobqueue.requirements.NetworkRequirementProvider;
/**
* Will be called once when the TextSecure process is created.
@@ -60,20 +58,16 @@ public class ApplicationContext extends Application {
}
private void initializeJobManager() {
Configuration configuration = new Configuration.Builder(this)
.minConsumerCount(1)
.injector(new ContextInjector(this))
.customLogger(new JobLogger())
.build();
this.jobManager = new JobManager(this, configuration);
this.jobManager = new JobManager(this, "TextSecureJobs",
new NetworkRequirementProvider(this),
new EncryptingJobSerializer(this), 5);
}
private void initializeGcmCheck() {
if (TextSecurePreferences.isPushRegistered(this) &&
TextSecurePreferences.getGcmRegistrationId(this) == null)
{
this.jobManager.addJob(new GcmRefreshJob());
this.jobManager.add(new GcmRefreshJob(this));
}
}

View File

@@ -6,12 +6,12 @@ import android.content.Intent;
import android.util.Log;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.path.android.jobqueue.JobManager;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.jobs.DeliveryReceiptJob;
import org.thoughtcrime.securesms.service.SendReceiveService;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.jobqueue.JobManager;
import org.whispersystems.libaxolotl.InvalidVersionException;
import org.whispersystems.textsecure.directory.Directory;
import org.whispersystems.textsecure.directory.NotInDirectoryException;
@@ -68,8 +68,9 @@ public class GcmBroadcastReceiver extends BroadcastReceiver {
if (!message.isReceipt()) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
jobManager.addJob(new DeliveryReceiptJob(message.getSource(), message.getTimestampMillis(),
message.getRelay()));
jobManager.add(new DeliveryReceiptJob(context, message.getSource(),
message.getTimestampMillis(),
message.getRelay()));
}
} catch (IOException e) {
Log.w(TAG, e);

View File

@@ -1,22 +0,0 @@
package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import com.path.android.jobqueue.BaseJob;
import com.path.android.jobqueue.di.DependencyInjector;
public class ContextInjector implements DependencyInjector {
private final Context context;
public ContextInjector(Context context) {
this.context = context;
}
@Override
public void inject(BaseJob job) {
if (job instanceof ContextJob) {
((ContextJob)job).setContext(context);
}
}
}

View File

@@ -2,15 +2,17 @@ package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import com.path.android.jobqueue.Job;
import com.path.android.jobqueue.Params;
import org.whispersystems.jobqueue.Job;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.dependencies.ContextDependent;
public abstract class ContextJob extends Job {
public abstract class ContextJob extends Job implements ContextDependent {
transient protected Context context;
protected transient Context context;
protected ContextJob(Params params) {
super(params);
protected ContextJob(Context context, JobParameters parameters) {
super(parameters);
this.context = context;
}
public void setContext(Context context) {

View File

@@ -1,10 +1,11 @@
package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.util.Log;
import com.path.android.jobqueue.Params;
import org.thoughtcrime.securesms.push.PushServiceSocketFactory;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.textsecure.push.PushServiceSocket;
import org.whispersystems.textsecure.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.textsecure.push.exceptions.PushNetworkException;
@@ -17,8 +18,12 @@ public class DeliveryReceiptJob extends ContextJob {
private final long timestamp;
private final String relay;
public DeliveryReceiptJob(String destination, long timestamp, String relay) {
super(new Params(Priorities.HIGH).requireNetwork().persist());
public DeliveryReceiptJob(Context context, String destination, long timestamp, String relay) {
super(context, JobParameters.newBuilder()
.withRequirement(new NetworkRequirement(context))
.withPersistence()
.withRetryCount(50)
.create());
this.destination = destination;
this.timestamp = timestamp;
@@ -36,21 +41,16 @@ public class DeliveryReceiptJob extends ContextJob {
}
@Override
protected void onCancel() {
public void onCanceled() {
Log.w(TAG, "Failed to send receipt after retry exhausted!");
}
@Override
protected boolean shouldReRunOnThrowable(Throwable throwable) {
public boolean onShouldRetry(Throwable throwable) {
Log.w(TAG, throwable);
if (throwable instanceof NonSuccessfulResponseCodeException) return false;
if (throwable instanceof PushNetworkException) return true;
if (throwable instanceof PushNetworkException) return true;
return false;
}
@Override
protected int getRetryLimit() {
return 50;
}
}

View File

@@ -0,0 +1,57 @@
package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import org.thoughtcrime.securesms.util.ParcelUtil;
import org.whispersystems.jobqueue.EncryptionKeys;
import org.whispersystems.jobqueue.Job;
import org.whispersystems.jobqueue.persistence.JavaJobSerializer;
import org.whispersystems.jobqueue.persistence.JobSerializer;
import org.whispersystems.libaxolotl.InvalidMessageException;
import org.whispersystems.textsecure.crypto.MasterCipher;
import org.whispersystems.textsecure.crypto.MasterSecret;
import java.io.IOException;
public class EncryptingJobSerializer implements JobSerializer {
private final JavaJobSerializer delegate;
public EncryptingJobSerializer(Context context) {
this.delegate = new JavaJobSerializer(context);
}
@Override
public String serialize(Job job) throws IOException {
String plaintext = delegate.serialize(job);
if (job.getEncryptionKeys() != null) {
MasterSecret masterSecret = ParcelUtil.deserialize(job.getEncryptionKeys().getEncoded(),
MasterSecret.CREATOR);
MasterCipher masterCipher = new MasterCipher(masterSecret);
return masterCipher.encryptBody(plaintext);
} else {
return plaintext;
}
}
@Override
public Job deserialize(EncryptionKeys keys, boolean encrypted, String serialized) throws IOException {
try {
String plaintext;
if (encrypted) {
MasterSecret masterSecret = ParcelUtil.deserialize(keys.getEncoded(), MasterSecret.CREATOR);
MasterCipher masterCipher = new MasterCipher(masterSecret);
plaintext = masterCipher.decryptBody(serialized);
} else {
plaintext = serialized;
}
return delegate.deserialize(keys, encrypted, plaintext);
} catch (InvalidMessageException e) {
throw new IOException(e);
}
}
}

View File

@@ -1,19 +1,19 @@
package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.path.android.jobqueue.Params;
import org.thoughtcrime.securesms.push.PushServiceSocketFactory;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.textsecure.push.PushServiceSocket;
import org.whispersystems.textsecure.push.exceptions.MismatchedDevicesException;
import org.whispersystems.textsecure.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.textsecure.push.exceptions.PushNetworkException;
public class GcmRefreshJob extends ContextJob {
@@ -21,8 +21,8 @@ public class GcmRefreshJob extends ContextJob {
public static final String REGISTRATION_ID = "312334754206";
public GcmRefreshJob() {
super(new Params(Priorities.NORMAL).requireNetwork());
public GcmRefreshJob(Context context) {
super(context, JobParameters.newBuilder().withRequirement(new NetworkRequirement(context)).create());
}
@Override
@@ -49,13 +49,14 @@ public class GcmRefreshJob extends ContextJob {
}
@Override
protected void onCancel() {
public void onCanceled() {
Log.w(TAG, "GCM reregistration failed after retry attempt exhaustion!");
}
@Override
protected boolean shouldReRunOnThrowable(Throwable throwable) {
public boolean onShouldRetry(Throwable throwable) {
if (throwable instanceof NonSuccessfulResponseCodeException) return false;
return true;
}
}

View File

@@ -1,27 +0,0 @@
package org.thoughtcrime.securesms.jobs;
import android.util.Log;
import com.path.android.jobqueue.log.CustomLogger;
public class JobLogger implements CustomLogger {
@Override
public boolean isDebugEnabled() {
return false;
}
@Override
public void d(String text, Object... args) {
Log.w("JobManager", String.format(text, args));
}
@Override
public void e(Throwable t, String text, Object... args) {
Log.w("JobManager", String.format(text, args), t);
}
@Override
public void e(String text, Object... args) {
Log.w("JobManager", String.format(text, args));
}
}

View File

@@ -1,8 +0,0 @@
package org.thoughtcrime.securesms.jobs;
public class Priorities {
public static final int NORMAL = 500;
public static final int HIGH = 1000;
}

View File

@@ -0,0 +1,28 @@
package org.thoughtcrime.securesms.util;
import android.os.Parcel;
import android.os.Parcelable;
public class ParcelUtil {
public static byte[] serialize(Parcelable parceable) {
Parcel parcel = Parcel.obtain();
parceable.writeToParcel(parcel, 0);
byte[] bytes = parcel.marshall();
parcel.recycle();
return bytes;
}
public static Parcel deserialize(byte[] bytes) {
Parcel parcel = Parcel.obtain();
parcel.unmarshall(bytes, 0, bytes.length);
parcel.setDataPosition(0);
return parcel;
}
public static <T> T deserialize(byte[] bytes, Parcelable.Creator<T> creator) {
Parcel parcel = deserialize(bytes);
return creator.createFromParcel(parcel);
}
}