mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 17:29:32 +01:00
Decrypt and process messages all in one transaction.
Giddy up
This commit is contained in:
@@ -5,6 +5,8 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -65,6 +67,11 @@ public class Data {
|
||||
return strings.get(key);
|
||||
}
|
||||
|
||||
public byte[] getStringAsBlob(@NonNull String key) {
|
||||
throwIfAbsent(strings, key);
|
||||
return Base64.decodeOrThrow(strings.get(key));
|
||||
}
|
||||
|
||||
public String getStringOrDefault(@NonNull String key, String defaultValue) {
|
||||
if (hasString(key)) return getString(key);
|
||||
else return defaultValue;
|
||||
@@ -349,6 +356,12 @@ public class Data {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder putBlobAsString(@NonNull String key, @NonNull byte[] value) {
|
||||
String serialized = Base64.encodeBytes(value);
|
||||
strings.put(key, serialized);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Data build() {
|
||||
return new Data(strings,
|
||||
stringArrays,
|
||||
|
||||
@@ -316,6 +316,10 @@ class JobController {
|
||||
return info.toString();
|
||||
}
|
||||
|
||||
synchronized boolean areQueuesEmpty(@NonNull Set<String> queueKeys) {
|
||||
return jobStorage.areQueuesEmpty(queueKeys);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private boolean chainExceedsMaximumInstances(@NonNull List<List<Job>> chain) {
|
||||
if (chain.size() == 1 && chain.get(0).size() == 1) {
|
||||
|
||||
@@ -42,7 +42,7 @@ public class JobManager implements ConstraintObserver.Notifier {
|
||||
|
||||
private static final String TAG = JobManager.class.getSimpleName();
|
||||
|
||||
public static final int CURRENT_VERSION = 7;
|
||||
public static final int CURRENT_VERSION = 8;
|
||||
|
||||
private final Application application;
|
||||
private final Configuration configuration;
|
||||
@@ -331,6 +331,31 @@ public class JobManager implements ConstraintObserver.Notifier {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can tell you if a queue is empty at the time of invocation. It is worth noting that the state
|
||||
* of the queue could change immediately after this method returns due to a call on some other
|
||||
* thread, and you should take that into consideration when using the result. If you want
|
||||
* something to happen within a queue, the safest course of action will always be to create a
|
||||
* job and place it in that queue.
|
||||
*
|
||||
* @return True if requested queue is empty at the time of invocation, otherwise false.
|
||||
*/
|
||||
@WorkerThread
|
||||
public boolean isQueueEmpty(@NonNull String queueKey) {
|
||||
return areQueuesEmpty(Collections.singleton(queueKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #isQueueEmpty(String)}
|
||||
*
|
||||
* @return True if *all* requested queues are empty at the time of invocation, otherwise false.
|
||||
*/
|
||||
@WorkerThread
|
||||
public boolean areQueuesEmpty(@NonNull Set<String> queueKeys) {
|
||||
waitUntilInitialized();
|
||||
return jobController.areQueuesEmpty(queueKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pokes the system to take another pass at the job queue.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.thoughtcrime.securesms.jobmanager.migrations;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.PushDatabase;
|
||||
import org.thoughtcrime.securesms.groups.BadGroupIdException;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobMigration;
|
||||
import org.thoughtcrime.securesms.jobs.FailingJob;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* We removed the messageId property from the job data and replaced it with a serialized envelope,
|
||||
* so we need to take jobs that referenced an ID and replace it with the envelope instead.
|
||||
*/
|
||||
public class PushDecryptMessageJobEnvelopeMigration extends JobMigration {
|
||||
|
||||
private static final String TAG = Log.tag(PushDecryptMessageJobEnvelopeMigration.class);
|
||||
|
||||
private final PushDatabase pushDatabase;
|
||||
|
||||
public PushDecryptMessageJobEnvelopeMigration(@NonNull Context context) {
|
||||
super(8);
|
||||
this.pushDatabase = DatabaseFactory.getPushDatabase(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull JobData migrate(@NonNull JobData jobData) {
|
||||
if ("PushDecryptJob".equals(jobData.getFactoryKey())) {
|
||||
Log.i(TAG, "Found a PushDecryptJob to migrate.");
|
||||
return migratePushDecryptMessageJob(pushDatabase, jobData);
|
||||
} else {
|
||||
return jobData;
|
||||
}
|
||||
}
|
||||
|
||||
private static @NonNull JobData migratePushDecryptMessageJob(@NonNull PushDatabase pushDatabase, @NonNull JobData jobData) {
|
||||
Data data = jobData.getData();
|
||||
|
||||
if (data.hasLong("message_id")) {
|
||||
long messageId = data.getLong("message_id");
|
||||
try {
|
||||
SignalServiceEnvelope envelope = pushDatabase.get(messageId);
|
||||
return jobData.withData(jobData.getData()
|
||||
.buildUpon()
|
||||
.putBlobAsString("envelope", envelope.serialize())
|
||||
.build());
|
||||
} catch (NoSuchMessageException e) {
|
||||
Log.w(TAG, "Failed to find envelope in DB! Failing.");
|
||||
return jobData.withFactoryKey(FailingJob.KEY);
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "No message_id property?");
|
||||
return jobData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,9 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface JobStorage {
|
||||
|
||||
@@ -32,6 +34,9 @@ public interface JobStorage {
|
||||
@WorkerThread
|
||||
int getJobCountForFactoryAndQueue(@NonNull String factoryKey, @NonNull String queueKey);
|
||||
|
||||
@WorkerThread
|
||||
boolean areQueuesEmpty(@NonNull Set<String> queueKeys);
|
||||
|
||||
@WorkerThread
|
||||
void updateJobRunningState(@NonNull String id, boolean isRunning);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user