WIP: further refactor on old jobs

This commit is contained in:
Ryan Zhao 2023-05-08 17:12:20 +10:00
parent 2ceb9e2bf4
commit b494088c3d
15 changed files with 9 additions and 485 deletions

View File

@ -65,9 +65,7 @@ import org.thoughtcrime.securesms.dependencies.DatabaseModule;
import org.thoughtcrime.securesms.emoji.EmojiSource;
import org.thoughtcrime.securesms.groups.OpenGroupManager;
import org.thoughtcrime.securesms.home.HomeActivity;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.jobs.JobManagerFactories;
import org.thoughtcrime.securesms.logging.AndroidLogger;
import org.thoughtcrime.securesms.logging.PersistentLogger;
import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger;
@ -130,7 +128,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
private ExpiringMessageManager expiringMessageManager;
private TypingStatusRepository typingStatusRepository;
private TypingStatusSender typingStatusSender;
private JobManager jobManager;
private ReadReceiptManager readReceiptManager;
private ProfileManager profileManager;
public MessageNotifier messageNotifier = null;
@ -227,7 +224,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
initializeProfileManager();
initializePeriodicTasks();
SSKEnvironment.Companion.configure(getTypingStatusRepository(), getReadReceiptManager(), getProfileManager(), messageNotifier, getExpiringMessageManager());
initializeJobManager();
initializeWebRtc();
initializeBlobProvider();
resubmitProfilePictureIfNeeded();
@ -284,10 +280,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
LocaleParser.Companion.configure(new LocaleParseHelper());
}
public JobManager getJobManager() {
return jobManager;
}
public ExpiringMessageManager getExpiringMessageManager() {
return expiringMessageManager;
}
@ -350,12 +342,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionLogger(originalHandler));
}
private void initializeJobManager() {
this.jobManager = new JobManager(this, new JobManager.Configuration.Builder()
.setConstraintObservers(JobManagerFactories.getConstraintObservers(this))
.build());
}
private void initializeExpiringMessageManager() {
this.expiringMessageManager = new ExpiringMessageManager(this);
}

View File

@ -42,13 +42,12 @@ import org.session.libsignal.messages.SignalServiceGroup
import org.session.libsignal.utilities.IdPrefix
import org.session.libsignal.utilities.KeyHelper
import org.session.libsignal.utilities.guava.Optional
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.database.model.MessageId
import org.thoughtcrime.securesms.database.model.ReactionRecord
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.groups.OpenGroupManager
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
import org.session.libsession.messaging.jobs.RetrieveProfileAvatarJob
import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.util.SessionMetaProtocol
import java.security.MessageDigest

View File

@ -1,12 +0,0 @@
package org.thoughtcrime.securesms.jobmanager;
import androidx.annotation.NonNull;
public interface ConstraintObserver {
void register(@NonNull Notifier notifier);
interface Notifier {
void onConstraintMet(@NonNull String reason);
}
}

View File

@ -1,26 +0,0 @@
package org.thoughtcrime.securesms.jobmanager;
import androidx.annotation.NonNull;
import org.session.libsession.messaging.jobs.Job;
import org.session.libsession.messaging.utilities.Data;
import java.util.HashMap;
import java.util.Map;
class JobInstantiator {
private final Map<String, Job.Factory> jobFactories;
JobInstantiator(@NonNull Map<String, Job.Factory> jobFactories) {
this.jobFactories = new HashMap<>(jobFactories);
}
public @NonNull Job instantiate(@NonNull String jobFactoryKey, @NonNull Data data) {
if (jobFactories.containsKey(jobFactoryKey)) {
return jobFactories.get(jobFactoryKey).create(data);
} else {
throw new IllegalStateException("Tried to instantiate a job with key '" + jobFactoryKey + "', but no matching factory was found.");
}
}
}

View File

@ -1,114 +0,0 @@
package org.thoughtcrime.securesms.jobmanager;
import android.app.Application;
import android.content.Intent;
import android.os.Build;
import androidx.annotation.NonNull;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.jobmanager.impl.DefaultExecutorFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutorService;
/**
* Allows the scheduling of durable jobs that will be run as early as possible.
*/
public class JobManager implements ConstraintObserver.Notifier {
private static final String TAG = JobManager.class.getSimpleName();
private final ExecutorService executor;
private final Set<EmptyQueueListener> emptyQueueListeners = new CopyOnWriteArraySet<>();
public JobManager(@NonNull Application application, @NonNull Configuration configuration) {
this.executor = configuration.getExecutorFactory().newSingleThreadExecutor("JobManager");
executor.execute(() -> {
for (ConstraintObserver constraintObserver : configuration.getConstraintObservers()) {
constraintObserver.register(this);
}
if (Build.VERSION.SDK_INT < 26) {
application.startService(new Intent(application, KeepAliveService.class));
}
wakeUp();
});
}
/**
* Adds a listener to that will be notified when the job queue has been drained.
*/
void addOnEmptyQueueListener(@NonNull EmptyQueueListener listener) {
executor.execute(() -> {
emptyQueueListeners.add(listener);
});
}
/**
* Removes a listener that was added via {@link #addOnEmptyQueueListener(EmptyQueueListener)}.
*/
void removeOnEmptyQueueListener(@NonNull EmptyQueueListener listener) {
executor.execute(() -> {
emptyQueueListeners.remove(listener);
});
}
@Override
public void onConstraintMet(@NonNull String reason) {
Log.i(TAG, "onConstraintMet(" + reason + ")");
wakeUp();
}
/**
* Pokes the system to take another pass at the job queue.
*/
void wakeUp() {}
public interface EmptyQueueListener {
void onQueueEmpty();
}
public static class Configuration {
private final ExecutorFactory executorFactory;
private final List<ConstraintObserver> constraintObservers;
private Configuration(@NonNull ExecutorFactory executorFactory,
@NonNull List<ConstraintObserver> constraintObservers)
{
this.executorFactory = executorFactory;
this.constraintObservers = constraintObservers;
}
@NonNull ExecutorFactory getExecutorFactory() {
return executorFactory;
}
@NonNull List<ConstraintObserver> getConstraintObservers() {
return constraintObservers;
}
public static class Builder {
private ExecutorFactory executorFactory = new DefaultExecutorFactory();
private List<ConstraintObserver> constraintObservers = new ArrayList<>();
public @NonNull Builder setConstraintObservers(@NonNull List<ConstraintObserver> constraintObservers) {
this.constraintObservers = constraintObservers;
return this;
}
public @NonNull Configuration build() {
return new Configuration(executorFactory,
new ArrayList<>(constraintObservers));
}
}
}
}

View File

@ -1,48 +0,0 @@
package org.thoughtcrime.securesms.jobmanager.impl;
import android.app.Application;
import android.app.job.JobInfo;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.jobmanager.Constraint;
import org.thoughtcrime.securesms.sms.TelephonyServiceState;
public class CellServiceConstraint implements Constraint {
public static final String KEY = "CellServiceConstraint";
private final Application application;
public CellServiceConstraint(@NonNull Application application) {
this.application = application;
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
public boolean isMet() {
TelephonyServiceState telephonyServiceState = new TelephonyServiceState();
return telephonyServiceState.isConnected(application);
}
@Override
public void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder) {
}
public static final class Factory implements Constraint.Factory<CellServiceConstraint> {
private final Application application;
public Factory(@NonNull Application application) {
this.application = application;
}
@Override
public CellServiceConstraint create() {
return new CellServiceConstraint(application);
}
}
}

View File

@ -1,38 +0,0 @@
package org.thoughtcrime.securesms.jobmanager.impl;
import android.app.Application;
import android.content.Context;
import androidx.annotation.NonNull;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import org.thoughtcrime.securesms.jobmanager.ConstraintObserver;
public class CellServiceConstraintObserver implements ConstraintObserver {
private static final String REASON = CellServiceConstraintObserver.class.getSimpleName();
private Notifier notifier;
public CellServiceConstraintObserver(@NonNull Application application) {
TelephonyManager telephonyManager = (TelephonyManager) application.getSystemService(Context.TELEPHONY_SERVICE);
ServiceStateListener serviceStateListener = new ServiceStateListener();
telephonyManager.listen(serviceStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
}
@Override
public void register(@NonNull Notifier notifier) {
this.notifier = notifier;
}
private class ServiceStateListener extends PhoneStateListener {
@Override
public void onServiceStateChanged(ServiceState serviceState) {
if (serviceState.getState() == ServiceState.STATE_IN_SERVICE && notifier != null) {
notifier.onConstraintMet(REASON);
}
}
}
}

View File

@ -1,36 +0,0 @@
package org.thoughtcrime.securesms.jobmanager.impl;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.jobmanager.ConstraintObserver;
public class NetworkConstraintObserver implements ConstraintObserver {
private static final String REASON = NetworkConstraintObserver.class.getSimpleName();
private final Application application;
public NetworkConstraintObserver(Application application) {
this.application = application;
}
@Override
public void register(@NonNull Notifier notifier) {
application.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
NetworkConstraint constraint = new NetworkConstraint.Factory(application).create();
if (constraint.isMet()) {
notifier.onConstraintMet(REASON);
}
}
}, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
}

View File

@ -1,48 +0,0 @@
package org.thoughtcrime.securesms.jobmanager.impl;
import android.app.Application;
import android.app.job.JobInfo;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.jobmanager.Constraint;
public class NetworkOrCellServiceConstraint implements Constraint {
public static final String KEY = "NetworkOrCellServiceConstraint";
private final NetworkConstraint networkConstraint;
private final CellServiceConstraint serviceConstraint;
public NetworkOrCellServiceConstraint(@NonNull Application application) {
networkConstraint = new NetworkConstraint.Factory(application).create();
serviceConstraint = new CellServiceConstraint.Factory(application).create();
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
public boolean isMet() {
return networkConstraint.isMet() || serviceConstraint.isMet();
}
@Override
public void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder) {
}
public static class Factory implements Constraint.Factory<NetworkOrCellServiceConstraint> {
private final Application application;
public Factory(@NonNull Application application) {
this.application = application;
}
@Override
public NetworkOrCellServiceConstraint create() {
return new NetworkOrCellServiceConstraint(application);
}
}
}

View File

@ -1,48 +0,0 @@
package org.thoughtcrime.securesms.jobmanager.impl;
import android.app.Application;
import android.app.job.JobInfo;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.jobmanager.Constraint;
import org.session.libsession.utilities.TextSecurePreferences;
public class SqlCipherMigrationConstraint implements Constraint {
public static final String KEY = "SqlCipherMigrationConstraint";
private final Application application;
private SqlCipherMigrationConstraint(@NonNull Application application) {
this.application = application;
}
@Override
public boolean isMet() {
return !TextSecurePreferences.getNeedsSqlCipherMigration(application);
}
@NonNull
@Override
public String getFactoryKey() {
return KEY;
}
@Override
public void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder) {
}
public static final class Factory implements Constraint.Factory<SqlCipherMigrationConstraint> {
private final Application application;
public Factory(@NonNull Application application) {
this.application = application;
}
@Override
public SqlCipherMigrationConstraint create() {
return new SqlCipherMigrationConstraint(application);
}
}
}

View File

@ -1,32 +0,0 @@
package org.thoughtcrime.securesms.jobmanager.impl;
import androidx.annotation.NonNull;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.thoughtcrime.securesms.jobmanager.ConstraintObserver;
public class SqlCipherMigrationConstraintObserver implements ConstraintObserver {
private static final String REASON = SqlCipherMigrationConstraintObserver.class.getSimpleName();
private Notifier notifier;
public SqlCipherMigrationConstraintObserver() {
EventBus.getDefault().register(this);
}
@Override
public void register(@NonNull Notifier notifier) {
this.notifier = notifier;
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(SqlCipherNeedsMigrationEvent event) {
if (notifier != null) notifier.onConstraintMet(REASON);
}
public static class SqlCipherNeedsMigrationEvent {
}
}

View File

@ -1,57 +0,0 @@
package org.thoughtcrime.securesms.jobs;
import android.app.Application;
import androidx.annotation.NonNull;
import org.session.libsession.messaging.jobs.Job;
import org.thoughtcrime.securesms.jobmanager.Constraint;
import org.thoughtcrime.securesms.jobmanager.ConstraintObserver;
import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraintObserver;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraintObserver;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class JobManagerFactories {
private static Collection<String> factoryKeys = new ArrayList<>();
public static Map<String, Job.Factory> getJobFactories() {
HashMap<String, Job.Factory> factoryHashMap = new HashMap<String, Job.Factory>() {{
put(LocalBackupJob.Companion.getKEY(), new LocalBackupJob.Factory());
put(RetrieveProfileAvatarJob.Companion.getKEY(), new RetrieveProfileAvatarJob.Factory());
put(UpdateApkJob.Companion.getKEY(), new UpdateApkJob.Factory());
}};
factoryKeys.addAll(factoryHashMap.keySet());
return factoryHashMap;
}
public static Map<String, Constraint.Factory> getConstraintFactories(@NonNull Application application) {
return new HashMap<String, Constraint.Factory>() {{
put(CellServiceConstraint.KEY, new CellServiceConstraint.Factory(application));
put(NetworkConstraint.KEY, new NetworkConstraint.Factory(application));
put(NetworkOrCellServiceConstraint.KEY, new NetworkOrCellServiceConstraint.Factory(application));
put(SqlCipherMigrationConstraint.KEY, new SqlCipherMigrationConstraint.Factory(application));
}};
}
public static List<ConstraintObserver> getConstraintObservers(@NonNull Application application) {
return Arrays.asList(new CellServiceConstraintObserver(application),
new NetworkConstraintObserver(application),
new SqlCipherMigrationConstraintObserver());
}
public static boolean hasFactoryForKey(String factoryKey) {
return factoryKeys.contains(factoryKey);
}
}

View File

@ -5,9 +5,8 @@ import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.utilities.SSKEnvironment
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
import org.session.libsession.messaging.jobs.RetrieveProfileAvatarJob
class ProfileManager : SSKEnvironment.ProfileManagerProtocol {

View File

@ -38,6 +38,7 @@ interface StorageProtocol {
fun getUserX25519KeyPair(): ECKeyPair
fun getUserProfile(): Profile
fun setUserProfilePictureURL(newProfilePicture: String)
fun
// Signal
fun getOrGenerateRegistrationID(): Int

View File

@ -1,10 +1,9 @@
package org.thoughtcrime.securesms.jobs
package org.session.libsession.messaging.jobs
import android.content.Context
import android.text.TextUtils
import org.session.libsession.avatars.AvatarHelper
import org.session.libsession.messaging.jobs.Job
import org.session.libsession.messaging.jobs.JobDelegate
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.utilities.Data
import org.session.libsession.utilities.DownloadUtilities.downloadFile
import org.session.libsession.utilities.TextSecurePreferences.Companion.setProfileAvatarId
@ -27,8 +26,6 @@ class RetrieveProfileAvatarJob(val profileAvatar: String, val recipientAddress:
override var failureCount: Int = 0
override val maxFailureCount: Int = 0
lateinit var context: Context
companion object {
val TAG = RetrieveProfileAvatarJob::class.simpleName
val KEY: String = "RetrieveProfileAvatarJob"
@ -39,8 +36,9 @@ class RetrieveProfileAvatarJob(val profileAvatar: String, val recipientAddress:
}
override fun execute(dispatcherName: String) {
val context = MessagingModuleConfiguration.shared.context
val storage = MessagingModuleConfiguration.shared.storage
val recipient = Recipient.from(context, recipientAddress, true)
val database = get(context).recipientDatabase()
val profileKey = recipient.resolve().profileKey
if (profileKey == null || (profileKey.size != 32 && profileKey.size != 16)) {
@ -56,7 +54,7 @@ class RetrieveProfileAvatarJob(val profileAvatar: String, val recipientAddress:
if (TextUtils.isEmpty(profileAvatar)) {
Log.w(TAG, "Removing profile avatar for: " + recipient.address.serialize())
AvatarHelper.delete(context, recipient.address)
database.setProfileAvatar(recipient, profileAvatar)
storage.setProfileAvatar(recipient, profileAvatar)
return
}
@ -75,7 +73,7 @@ class RetrieveProfileAvatarJob(val profileAvatar: String, val recipientAddress:
if (recipient.isLocalNumber) {
setProfileAvatarId(context, SecureRandom().nextInt())
}
database.setProfileAvatar(recipient, profileAvatar)
storage.setProfileAvatar(recipient, profileAvatar)
}
override fun serialize(): Data {