Apply better strategy for dependency init.

This commit is contained in:
Alex Hart 2020-11-30 16:09:48 -04:00
parent dcb16378c8
commit 4ae0f3999c

View file

@ -12,7 +12,6 @@ import org.thoughtcrime.securesms.groups.GroupsV2Authorization;
import org.thoughtcrime.securesms.groups.GroupsV2AuthorizationMemoryValueCache; import org.thoughtcrime.securesms.groups.GroupsV2AuthorizationMemoryValueCache;
import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor; import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor;
import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.keyvalue.KeyValueStore;
import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.megaphone.MegaphoneRepository; import org.thoughtcrime.securesms.megaphone.MegaphoneRepository;
import org.thoughtcrime.securesms.messages.BackgroundMessageRetriever; import org.thoughtcrime.securesms.messages.BackgroundMessageRetriever;
@ -43,78 +42,87 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
*/ */
public class ApplicationDependencies { public class ApplicationDependencies {
private static Application application; private static final Object LOCK = new Object();
private static Provider provider; private static final Object FRAME_RATE_TRACKER_LOCK = new Object();
private static SignalServiceAccountManager accountManager; private static Application application;
private static SignalServiceMessageSender messageSender; private static Provider provider;
private static SignalServiceMessageReceiver messageReceiver; private static MessageNotifier messageNotifier;
private static IncomingMessageObserver incomingMessageObserver; private static TrimThreadsByDateManager trimThreadsByDateManager;
private static IncomingMessageProcessor incomingMessageProcessor;
private static BackgroundMessageRetriever backgroundMessageRetriever; private static volatile SignalServiceAccountManager accountManager;
private static LiveRecipientCache recipientCache; private static volatile SignalServiceMessageSender messageSender;
private static JobManager jobManager; private static volatile SignalServiceMessageReceiver messageReceiver;
private static FrameRateTracker frameRateTracker; private static volatile IncomingMessageObserver incomingMessageObserver;
private static KeyValueStore keyValueStore; private static volatile IncomingMessageProcessor incomingMessageProcessor;
private static MegaphoneRepository megaphoneRepository; private static volatile BackgroundMessageRetriever backgroundMessageRetriever;
private static GroupsV2Authorization groupsV2Authorization; private static volatile LiveRecipientCache recipientCache;
private static GroupsV2StateProcessor groupsV2StateProcessor; private static volatile JobManager jobManager;
private static GroupsV2Operations groupsV2Operations; private static volatile FrameRateTracker frameRateTracker;
private static EarlyMessageCache earlyMessageCache; private static volatile MegaphoneRepository megaphoneRepository;
private static MessageNotifier messageNotifier; private static volatile GroupsV2Authorization groupsV2Authorization;
private static TrimThreadsByDateManager trimThreadsByDateManager; private static volatile GroupsV2StateProcessor groupsV2StateProcessor;
private static TypingStatusRepository typingStatusRepository; private static volatile GroupsV2Operations groupsV2Operations;
private static TypingStatusSender typingStatusSender; private static volatile EarlyMessageCache earlyMessageCache;
private static volatile TypingStatusRepository typingStatusRepository;
private static volatile TypingStatusSender typingStatusSender;
@MainThread @MainThread
public static synchronized void init(@NonNull Application application, @NonNull Provider provider) { public static void init(@NonNull Application application, @NonNull Provider provider) {
if (ApplicationDependencies.application != null || ApplicationDependencies.provider != null) { synchronized (LOCK) {
throw new IllegalStateException("Already initialized!"); if (ApplicationDependencies.application != null || ApplicationDependencies.provider != null) {
} throw new IllegalStateException("Already initialized!");
}
ApplicationDependencies.application = application; ApplicationDependencies.application = application;
ApplicationDependencies.provider = provider; ApplicationDependencies.provider = provider;
ApplicationDependencies.messageNotifier = provider.provideMessageNotifier(); ApplicationDependencies.messageNotifier = provider.provideMessageNotifier();
ApplicationDependencies.trimThreadsByDateManager = provider.provideTrimThreadsByDateManager(); ApplicationDependencies.trimThreadsByDateManager = provider.provideTrimThreadsByDateManager();
}
} }
public static @NonNull Application getApplication() { public static @NonNull Application getApplication() {
assertInitialization();
return application; return application;
} }
public static synchronized @NonNull SignalServiceAccountManager getSignalServiceAccountManager() { public static @NonNull SignalServiceAccountManager getSignalServiceAccountManager() {
assertInitialization();
if (accountManager == null) { if (accountManager == null) {
accountManager = provider.provideSignalServiceAccountManager(); synchronized (LOCK) {
if (accountManager == null) {
accountManager = provider.provideSignalServiceAccountManager();
}
}
} }
return accountManager; return accountManager;
} }
public static synchronized @NonNull GroupsV2Authorization getGroupsV2Authorization() { public static @NonNull GroupsV2Authorization getGroupsV2Authorization() {
assertInitialization();
if (groupsV2Authorization == null) { if (groupsV2Authorization == null) {
GroupsV2Authorization.ValueCache authCache = new GroupsV2AuthorizationMemoryValueCache(SignalStore.groupsV2AuthorizationCache()); synchronized (LOCK) {
groupsV2Authorization = new GroupsV2Authorization(getSignalServiceAccountManager().getGroupsV2Api(), authCache); if (groupsV2Authorization == null) {
GroupsV2Authorization.ValueCache authCache = new GroupsV2AuthorizationMemoryValueCache(SignalStore.groupsV2AuthorizationCache());
groupsV2Authorization = new GroupsV2Authorization(getSignalServiceAccountManager().getGroupsV2Api(), authCache);
}
}
} }
return groupsV2Authorization; return groupsV2Authorization;
} }
public static synchronized @NonNull GroupsV2Operations getGroupsV2Operations() { public static @NonNull GroupsV2Operations getGroupsV2Operations() {
assertInitialization();
if (groupsV2Operations == null) { if (groupsV2Operations == null) {
groupsV2Operations = provider.provideGroupsV2Operations(); synchronized (LOCK) {
if (groupsV2Operations == null) {
groupsV2Operations = provider.provideGroupsV2Operations();
}
}
} }
return groupsV2Operations; return groupsV2Operations;
} }
public static synchronized @NonNull KeyBackupService getKeyBackupService(@NonNull KbsEnclave enclave) { public static @NonNull KeyBackupService getKeyBackupService(@NonNull KbsEnclave enclave) {
return getSignalServiceAccountManager().getKeyBackupService(IasKeyStore.getIasKeyStore(application), return getSignalServiceAccountManager().getKeyBackupService(IasKeyStore.getIasKeyStore(application),
enclave.getEnclaveName(), enclave.getEnclaveName(),
Hex.fromStringOrThrow(enclave.getServiceId()), Hex.fromStringOrThrow(enclave.getServiceId()),
@ -122,144 +130,160 @@ public class ApplicationDependencies {
10); 10);
} }
public static synchronized @NonNull GroupsV2StateProcessor getGroupsV2StateProcessor() { public static @NonNull GroupsV2StateProcessor getGroupsV2StateProcessor() {
assertInitialization();
if (groupsV2StateProcessor == null) { if (groupsV2StateProcessor == null) {
groupsV2StateProcessor = new GroupsV2StateProcessor(application); synchronized (LOCK) {
if (groupsV2StateProcessor == null) {
groupsV2StateProcessor = new GroupsV2StateProcessor(application);
}
}
} }
return groupsV2StateProcessor; return groupsV2StateProcessor;
} }
public static synchronized @NonNull SignalServiceMessageSender getSignalServiceMessageSender() { public static @NonNull SignalServiceMessageSender getSignalServiceMessageSender() {
assertInitialization(); synchronized (LOCK) {
if (messageSender == null) {
if (messageSender == null) { messageSender = provider.provideSignalServiceMessageSender();
messageSender = provider.provideSignalServiceMessageSender(); } else {
} else { messageSender.update(
messageSender.update( IncomingMessageObserver.getPipe(),
IncomingMessageObserver.getPipe(), IncomingMessageObserver.getUnidentifiedPipe(),
IncomingMessageObserver.getUnidentifiedPipe(), TextSecurePreferences.isMultiDevice(application));
TextSecurePreferences.isMultiDevice(application)); }
} }
return messageSender; return messageSender;
} }
public static synchronized @NonNull SignalServiceMessageReceiver getSignalServiceMessageReceiver() { public static @NonNull SignalServiceMessageReceiver getSignalServiceMessageReceiver() {
assertInitialization();
if (messageReceiver == null) { if (messageReceiver == null) {
messageReceiver = provider.provideSignalServiceMessageReceiver(); synchronized (LOCK) {
if (messageReceiver == null) {
messageReceiver = provider.provideSignalServiceMessageReceiver();
}
}
} }
return messageReceiver; return messageReceiver;
} }
public static synchronized void resetSignalServiceMessageReceiver() { public static void resetSignalServiceMessageReceiver() {
assertInitialization(); synchronized (LOCK) {
messageReceiver = null; messageReceiver = null;
}
} }
public static synchronized @NonNull SignalServiceNetworkAccess getSignalServiceNetworkAccess() { public static @NonNull SignalServiceNetworkAccess getSignalServiceNetworkAccess() {
assertInitialization();
return provider.provideSignalServiceNetworkAccess(); return provider.provideSignalServiceNetworkAccess();
} }
public static synchronized @NonNull IncomingMessageProcessor getIncomingMessageProcessor() { public static @NonNull IncomingMessageProcessor getIncomingMessageProcessor() {
assertInitialization();
if (incomingMessageProcessor == null) { if (incomingMessageProcessor == null) {
incomingMessageProcessor = provider.provideIncomingMessageProcessor(); synchronized (LOCK) {
if (incomingMessageProcessor == null) {
incomingMessageProcessor = provider.provideIncomingMessageProcessor();
}
}
} }
return incomingMessageProcessor; return incomingMessageProcessor;
} }
public static synchronized @NonNull BackgroundMessageRetriever getBackgroundMessageRetriever() { public static @NonNull BackgroundMessageRetriever getBackgroundMessageRetriever() {
assertInitialization();
if (backgroundMessageRetriever == null) { if (backgroundMessageRetriever == null) {
backgroundMessageRetriever = provider.provideBackgroundMessageRetriever(); synchronized (LOCK) {
if (backgroundMessageRetriever == null) {
backgroundMessageRetriever = provider.provideBackgroundMessageRetriever();
}
}
} }
return backgroundMessageRetriever; return backgroundMessageRetriever;
} }
public static synchronized @NonNull LiveRecipientCache getRecipientCache() { public static @NonNull LiveRecipientCache getRecipientCache() {
assertInitialization();
if (recipientCache == null) { if (recipientCache == null) {
recipientCache = provider.provideRecipientCache(); synchronized (LOCK) {
if (recipientCache == null) {
recipientCache = provider.provideRecipientCache();
}
}
} }
return recipientCache; return recipientCache;
} }
public static synchronized @NonNull JobManager getJobManager() { public static @NonNull JobManager getJobManager() {
assertInitialization();
if (jobManager == null) { if (jobManager == null) {
jobManager = provider.provideJobManager(); synchronized (LOCK) {
if (jobManager == null) {
jobManager = provider.provideJobManager();
}
}
} }
return jobManager; return jobManager;
} }
public static synchronized @NonNull FrameRateTracker getFrameRateTracker() { public static @NonNull FrameRateTracker getFrameRateTracker() {
assertInitialization();
if (frameRateTracker == null) { if (frameRateTracker == null) {
frameRateTracker = provider.provideFrameRateTracker(); synchronized (FRAME_RATE_TRACKER_LOCK) {
if (frameRateTracker == null) {
frameRateTracker = provider.provideFrameRateTracker();
}
}
} }
return frameRateTracker; return frameRateTracker;
} }
public static synchronized @NonNull MegaphoneRepository getMegaphoneRepository() { public static @NonNull MegaphoneRepository getMegaphoneRepository() {
assertInitialization();
if (megaphoneRepository == null) { if (megaphoneRepository == null) {
megaphoneRepository = provider.provideMegaphoneRepository(); synchronized (LOCK) {
if (megaphoneRepository == null) {
megaphoneRepository = provider.provideMegaphoneRepository();
}
}
} }
return megaphoneRepository; return megaphoneRepository;
} }
public static synchronized @NonNull EarlyMessageCache getEarlyMessageCache() { public static @NonNull EarlyMessageCache getEarlyMessageCache() {
assertInitialization();
if (earlyMessageCache == null) { if (earlyMessageCache == null) {
earlyMessageCache = provider.provideEarlyMessageCache(); synchronized (LOCK) {
if (earlyMessageCache == null) {
earlyMessageCache = provider.provideEarlyMessageCache();
}
}
} }
return earlyMessageCache; return earlyMessageCache;
} }
public static synchronized @NonNull MessageNotifier getMessageNotifier() { public static @NonNull MessageNotifier getMessageNotifier() {
assertInitialization();
return messageNotifier; return messageNotifier;
} }
public static synchronized @NonNull IncomingMessageObserver getIncomingMessageObserver() { public static @NonNull IncomingMessageObserver getIncomingMessageObserver() {
assertInitialization();
if (incomingMessageObserver == null) { if (incomingMessageObserver == null) {
incomingMessageObserver = provider.provideIncomingMessageObserver(); synchronized (LOCK) {
if (incomingMessageObserver == null) {
incomingMessageObserver = provider.provideIncomingMessageObserver();
}
}
} }
return incomingMessageObserver; return incomingMessageObserver;
} }
public static synchronized @NonNull TrimThreadsByDateManager getTrimThreadsByDateManager() { public static @NonNull TrimThreadsByDateManager getTrimThreadsByDateManager() {
assertInitialization(); return trimThreadsByDateManager;
return trimThreadsByDateManager;
} }
public static TypingStatusRepository getTypingStatusRepository() { public static TypingStatusRepository getTypingStatusRepository() {
assertInitialization();
if (typingStatusRepository == null) { if (typingStatusRepository == null) {
typingStatusRepository = provider.provideTypingStatusRepository(); typingStatusRepository = provider.provideTypingStatusRepository();
} }
@ -268,8 +292,6 @@ public class ApplicationDependencies {
} }
public static TypingStatusSender getTypingStatusSender() { public static TypingStatusSender getTypingStatusSender() {
assertInitialization();
if (typingStatusSender == null) { if (typingStatusSender == null) {
typingStatusSender = provider.provideTypingStatusSender(); typingStatusSender = provider.provideTypingStatusSender();
} }
@ -277,12 +299,6 @@ public class ApplicationDependencies {
return typingStatusSender; return typingStatusSender;
} }
private static void assertInitialization() {
if (application == null || provider == null) {
throw new UninitializedException();
}
}
public interface Provider { public interface Provider {
@NonNull GroupsV2Operations provideGroupsV2Operations(); @NonNull GroupsV2Operations provideGroupsV2Operations();
@NonNull SignalServiceAccountManager provideSignalServiceAccountManager(); @NonNull SignalServiceAccountManager provideSignalServiceAccountManager();
@ -302,10 +318,4 @@ public class ApplicationDependencies {
@NonNull TypingStatusRepository provideTypingStatusRepository(); @NonNull TypingStatusRepository provideTypingStatusRepository();
@NonNull TypingStatusSender provideTypingStatusSender(); @NonNull TypingStatusSender provideTypingStatusSender();
} }
private static class UninitializedException extends IllegalStateException {
private UninitializedException() {
super("You must call init() first!");
}
}
} }